home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers1.zip / EXP16.ASM < prev    next >
Assembly Source File  |  1992-01-23  |  64KB  |  2,916 lines

  1. version    equ 3
  2. DEBUG   equ 0
  3. ;History:1518,1
  4.  
  5. ;  Copyright 1991 Russell Nelson
  6.  
  7. ;   This program is free software; you can redistribute it and/or modify
  8. ;   it under the terms of the GNU General Public License as published by
  9. ;   the Free Software Foundation, version 1.
  10. ;
  11. ;   This program is distributed in the hope that it will be useful,
  12. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;   GNU General Public License for more details.
  15. ;
  16. ;   You should have received a copy of the GNU General Public License
  17. ;   along with this program; if not, write to the Free Software
  18. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     include    defs.asm
  21.  
  22. code    segment    word public
  23.     assume    cs:code, ds:code
  24.  
  25. ;
  26. ;    Waits for SCB command unit to become idle
  27. ;
  28. ;    MUST NOT TRASH CX OR THE ISSUE_COMMAND PROCEDURE WILL FAIL
  29.  
  30. deb            macro    xxx
  31. if DEBUG
  32.                push bx
  33.                push ds
  34.  
  35.                mov bx,0b800h
  36.                mov ds,bx
  37.                mov bx,word ptr xxx
  38.                add bx,40
  39.                shl bx,1
  40.                shl bx,1
  41.                inc byte ptr ds:[bx]
  42.                pop ds
  43.                pop bx
  44. endif
  45.                endm
  46.  
  47.  
  48. cmd_clear    macro
  49.     local    exit
  50.  
  51.     lea    dx, [bp].@SCB_CMD        ;BP -> I/O Base
  52.  
  53.     in    ax, dx                ;Read SCB command
  54.     or    ax, ax                ;Wait for command accepted
  55.     jz    exit
  56.  
  57.     call    cmd_wait
  58. exit:
  59.     endm
  60.  
  61. ;
  62. ; Drives channel attention to the 586.  We don't care whats in AX, the write
  63. ; will cause the ASIC to drive CA to the 586.
  64. ;
  65. issue_ca    MACRO
  66.     lea    dx, [bp].@CA_Ctrl
  67.     out    dx, al
  68.       endm
  69.  
  70.  
  71. ;
  72. ;
  73. ;  Enable and disable barts interrupts.
  74. ;
  75. enable_board_ints    macro
  76.     lea    dx, [bp].@Sel_IRQ
  77.     mov    al, encoded_int_no
  78.     or    al, 08h
  79.     out    dx, al
  80.     endm
  81.  
  82. disable_board_ints    macro
  83.     lea    dx, [bp].@Sel_IRQ
  84.     mov    al, encoded_int_no
  85.     out    dx, al
  86.     endm
  87.  
  88.  
  89. RxBufferSize        equ    1518+14+18    ;Max Rx packet+MAC header+
  90.                         ; 18 (alignment)
  91. TxBufferSize        equ    1518+14+20    ;Max Tx packet+MAC header+
  92.                         ; 20 (alignment)
  93.  
  94. ;    82586 Structure definitions
  95.  
  96. SysConfigPtr    struc
  97.     SCP_SystemBus        dw    ?
  98.                 dw    2 dup (?)
  99.     SCP_ISCP_Ptr_low    dw    ?
  100.     SCP_ISCP_Ptr_high    dw    ?
  101. SysConfigPtr    ends
  102.  
  103.  
  104. ;----------------------------------------------------------------
  105. ; Note: The @ addresses are the I/O address offsets from [bp].
  106. ;----------------------------------------------------------------
  107.  
  108. ; The SCP is at location XXX6H.  Since the
  109. ; SMB pointers must have the low order 5 bits
  110. ; zero, we assume that the SMP pointer will
  111. ; be set to XXE0H
  112. @SysConfigPtr    struc
  113.                 db    8000h dup (?)
  114.                 dw    ?
  115.                 dw    ?
  116.                 dw    ?
  117.     @SCP_SystemBus        dw    ?
  118.                 dw    2 dup (?)
  119.     @SCP_ISCP_Ptr_low    dw    ?
  120.     @SCP_ISCP_Ptr_high    dw    ?
  121. @SysConfigPtr    ends
  122.  
  123.  
  124. ISysConfigPtr    struc
  125.     ISCP_Busy        dw    ?
  126.     ISCP_SCB_Offset        dw    ?
  127.     ISCP_Ptr_low        dw    ?
  128.     ISCP_Ptr_high        dw    ?
  129. ISysConfigPtr    ends
  130.  
  131.  
  132. ; NOTE: Access to the SCB through the shadow
  133. ; registers is done by setting the SMB_PTR to
  134. ; the ISCP base address and then using this
  135. ; structure.  This is because the SCB address
  136. ; does not start on a 32 byte boundary as
  137. ; as required for the SMB_PTR.
  138.  
  139. @ISysConfigPtr    struc
  140.                 db    4000h dup (?)
  141.     @ISCP_Busy        dw    ?
  142.     @ISCP_SCB_Offset    dw    ?
  143.     @ISCP_SCB_Ptr_low    dw    ?
  144.     @ISCP_SCB_Ptr_high    dw    ?
  145.     @SCB_Status        dw    ?
  146.     @SCB_Command        dw    ?
  147.     @SCB_CommandList    dw    ?
  148.     @SCB_RecBlockList    dw    ?
  149.                 db    4000h - 16 dup (?)
  150.     @SCB_CRC_Errors    dw    ?
  151.     @SCB_ALN_Errors    dw    ?
  152.     @SCB_RSC_Errors    dw    ?
  153.     @SCB_OVR_Errors    dw    ?
  154. @ISysConfigPtr    ends
  155.  
  156.  
  157. SystemControlBlock    struc
  158.     SCB_Status        dw    ?
  159.     SCB_Command        dw    ?
  160.     SCB_CommandList     dw    ?
  161.     SCB_RecBlockList    dw    ?
  162.     SCB_CRC_Errors        dw    ?
  163.     SCB_ALN_Errors        dw    ?
  164.     SCB_RSC_Errors        dw    ?
  165.     SCB_OVR_Errors        dw    ?
  166. SystemControlBlock    ends
  167.  
  168. ; NOTE: The SCB shadow register structure is
  169. ; part of the ISysConfigPtr shadow register
  170. ; structure.
  171.  
  172. ReceiveBlock    struc
  173.     FD_Status        dw    ?
  174.     FD_Command        dw    ?
  175.     FD_Link                dw    ?
  176.     FD_RBD_Offset        dw    ?
  177.     RBD_ByteCount        dw    ?
  178.     RBD_Link        dw    ?
  179.     RBD_RB_Address_low    dw    ?
  180.     RBD_RB_Address_high    dw    ?
  181.     RBD_Size        dw    ?
  182.     RB_Data        db    RxBufferSize dup (?)
  183. ReceiveBlock    ends
  184.  
  185. ReceiveBlock_data    struc
  186.     IPX_FD_Status            dw    ?
  187.     IPX_FD_Command            dw    ?
  188.     IPX_FD_Link            dw    ?
  189.     IPX_FD_RBD_Offset        dw    ?
  190.     IPX_RBD_ByteCount        dw    ?
  191.     IPX_RBD_Link            dw    ?
  192.     IPX_RBD_RB_Address_low             dw    ?
  193.     IPX_RBD_RB_Address_high            dw    ?
  194.     IPX_RBD_Size            dw    ?
  195.     IPX_DestAddr_HIGH        dw    ?
  196.     IPX_DestAddr_MID        dw    ?
  197.     IPX_DestAddr_LOW        dw    ?
  198.     IPX_SourceAddr_HIGH         dw    ?
  199.     IPX_SourceAddr_MID        dw    ?
  200.     IPX_SourceAddr_LOW        dw    ?
  201.     IPX_LengthTypeField         dw    ?
  202. ReceiveBlock_data    ends
  203.  
  204.  
  205. @ReceiveBlock    struc
  206.                 db    4000h dup (?)
  207.     @FD_Status        dw    ?
  208.     @FD_Command        dw    ?
  209.     @FD_Link        dw    ?
  210.     @FD_RBD_Offset        dw    ?
  211.     @RBD_ByteCount        dw    ?
  212.     @RBD_Link        dw    ?
  213.     @RBD_RB_Address_low    dw    ?
  214.     @RBD_RB_Address_high    dw    ?
  215.                 db    4000h - 16 dup (?)
  216.     @RBD_Size        dw    ?
  217. ; Ethernet Packet Data
  218.     @DestAddr_HIGH            dw    ?
  219.     @DestAddr_MID        dw    ?
  220.     @DestAddr_LOW        dw    ?
  221.     @SourceAddr_HIGH     dw    ?
  222.     @SourceAddr_MID            dw    ?
  223.     @SourceAddr_LOW            dw    ?
  224.     @LengthTypeField     dw    ?
  225. @ReceiveBlock    ends
  226.  
  227. SendBlock    struc
  228.     TxCB_Status        dw    ?
  229.     TxCB_Command        dw    ?
  230.     TxCB_Link        dw    ?
  231.     TxCB_TBD_Offset            dw    ?
  232.     TBD_ByteCount        dw    ?
  233.     TBD_Link        dw    ?
  234.     TBD_TB_Address_low    dw    ?
  235.     TBD_TB_Address_high    dw    ?
  236.     TB_Data        db    TxBufferSize dup (?)
  237. SendBlock    ends
  238.  
  239.  
  240. @SendBlock    struc
  241.                 db    4000h dup (?)
  242.     @TxCB_Status        dw    ?
  243.     @TxCB_Command        dw    ?
  244.     @TxCB_Link        dw    ?
  245.     @TxCB_TBD_Offset    dw    ?
  246.     @TBD_ByteCount    dw    ?
  247.     @TBD_Link        dw    ?
  248.     @TBD_TB_Address_low    dw    ?
  249.     @TBD_TB_Address_high    dw    ?
  250.                 db    4000h - 16 dup (?)
  251.     @TB_Data        db    TxBufferSize dup (?)
  252. @SendBlock    ends
  253.  
  254.  
  255. CommandBlock    struc                     ;Set command block
  256.     CB_Status    dw    ?            ; Size for largest
  257.     CB_Command    dw    ?            ; command.  The Dump
  258.     CB_Link    dw    ?                ; command needs a 170
  259.     CB_Param0    dw    ?            ; byte area.  The 14
  260.             db    170+14 dup (?)         ; extra bytes are
  261. CommandBlock    ends                    ; padding to make the
  262.                             ; size of this struc
  263.                             ; boundary.
  264. @CommandBlock    struc
  265.             db    4000h dup (?)        ;Set command block
  266.     @CB_Status    dw    ?            ; Size for largest
  267.     @CB_Command    dw    ?            ; command.  The Dump
  268.     @CB_Link    dw    ?            ; command needs a 170
  269.     @CB_Parm0    dw    ?            ; byte area.  The 14
  270.             db     170+14 dup (?)      ; extra bytes are
  271. @CommandBlock    ends                    ; padding to make the
  272.                             ; size of this struc
  273.                             ; align on a 16 byte
  274. SCPS            equ    SysConfigPtr
  275. ISCPS            equ    ISysConfigPtr
  276. SCBS            equ    SystemControlBlock
  277.  
  278. ; System ControlBlock.
  279.  
  280. Bit_CX        equ    8000h
  281. Bit_FR        equ    4000h
  282. Bit_CNA        equ    2000h
  283. Bit_RNR        equ    1000h
  284.  
  285. ;  System Control Block's control unit statuses
  286.  
  287. CUS_Idle        equ    0000h
  288. CUS_Suspended        equ    0100h
  289. CUS_Active        equ    0200h
  290. CUS_Mask        equ    0300h
  291.  
  292. ;  System Control Block's receive unit statuses.
  293. RUS_Idle        equ    0000h
  294. RUS_Suspend        equ    0010h
  295. RUS_No_Resource        equ    0020h
  296. RUS_Ready        equ    0040h
  297.  
  298. ;  System Control Block's control unit commands
  299. CUC_NOP            equ    0000h
  300. CUC_Start        equ    0100h
  301. CUC_Resume        equ    0200h
  302. CUC_Suspend        equ    0300h
  303. CUC_Abort        equ    0400h
  304.  
  305. ;  System Control Block's receive unit commands
  306. RUC_NOP            equ    0000h
  307. RUC_Start        equ    0010h
  308. RUC_Resume        equ    0020h
  309. RUC_Suspend        equ    0030h
  310. RUC_Abort        equ    0040h
  311.  
  312.  
  313. ; General Action Command Block.
  314.  
  315. GA_NOP            equ    0000h
  316. GA_IA_Setup        equ    0001h
  317. GA_Configure        equ    0002h
  318. GA_MC_Setup        equ    0003h
  319. GA_Transmit        equ    0004h
  320. GA_TDR            equ    0005h
  321. GA_Dump             equ    0006h
  322. GA_Diagnose        equ    0007h
  323.  
  324. lock_bit_address    EQU    01H
  325. lock_bit_mask        EQU    0000000000000001B
  326. iochrdy_mask        EQU    00010000B
  327. iochrdy_test_mask    EQU    00100000B
  328. iochrdy_test_result    EQU    01000000B
  329. iochrdy_early        EQU    00000000B
  330. iochrdy_late        EQU    00010000B
  331.  
  332.  
  333. ; Common Bits.
  334.  
  335. Bit_C            equ    8000h    ; Command complete.
  336. Bit_B            equ    4000h    ; Busy executing command.
  337. Bit_OK            equ    2000h    ; Error free completion.
  338. Bit_A            equ    1000h    ; Command aborted.
  339.  
  340. Bit_EL            equ    8000h    ; End of list.
  341. Bit_EOF            equ    8000h    ; End of frame.
  342. byte_Bit_EOF         equ    80h    ; End of frame.
  343. Bit_S            equ    4000h    ; Suspend after completion.
  344. Bit_I            equ    2000h    ; Interrupt after completion.
  345.  
  346. Bit_S11                 equ     0800h
  347. Bit_S10            equ    0400h
  348. Bit_S9            equ    0200h
  349. Bit_S8            equ    0100h
  350. Bit_S7            equ    0080h
  351. Bit_S6            equ    0040h
  352. Bit_S5            equ    0020h
  353.  
  354. ACK_INT_Mask         equ    0f000h
  355. MaxCollisions        equ    0020h
  356. Ready            equ    0040h
  357.  
  358. LNK_OK                  equ     8000h
  359. XCVR_PRB                equ     4000h
  360. ET_OPN                  equ     2000h
  361. ET_SRT                  equ     1000h
  362. TDR_TIME                equ     07ffh
  363.  
  364. ;
  365. ; equates and definitions:
  366. ;
  367. EOI            equ    020h    ;End-of-interrupt command.
  368. Master_PIC        equ    020h    ;1st Interrupt-Control port.
  369. Slave_PIC        equ    0A0h    ;2nd Interrupt-Control port.
  370.  
  371. Bart_Board_ID        equ    0BABAH
  372.  
  373. Number_of_Tx_Buffers    equ    1
  374.  
  375. _586_Reset        equ    0080H
  376. ASIC_Reset        equ    0040H
  377.  
  378. bus_width        equ    0    ;16 bit, use for initialize
  379. initialize_586        equ    1
  380.  
  381. ;
  382. ; Timer equates
  383. ;
  384. one_mil     EQU    02387
  385. ten_mils    EQU    23866
  386.  
  387.  
  388. ;
  389. ;  EEPROM equATES
  390. ;
  391. EE_SK        equ    00000001B    ;EEPROM shift clock (1 = high, 0 = low)
  392. EE_CS        equ    00000010B    ;EEPROM chip select (1 = high, 0 = low)
  393. EE_DI        equ    00000100B    ;EEPROM data in (set to 1 for writing data to EEPROM)
  394. EE_DO        equ    00001000B    ;EEPROM data out
  395. EE_tick        equ    10
  396.  
  397. EEPROM_read_opcode     equ    110B
  398. EEPROM_write_opcode    equ    101B
  399. EEPROM_erase_opcode    equ    111B
  400. EEPROM_EWEN_opcode     equ    10011B        ;Erase/write enable
  401. EEPROM_EWDS_opcode     equ    10000B        ;Erase/write disable
  402.  
  403. TIME_OUT_VALUE    equ    0FFFFh
  404.  
  405. loopback_enable    equ    00000010B
  406.  
  407. _64K_not_32K        db    0    ;<>0 if we have 64K of memory.
  408. _16_not_8_bit_slot    db    0    ;<>0 if we're in a 16-bit slot.
  409. connection_type        db    ?
  410.  
  411. ;Memory Sizes
  412. mem_size_address    equ    00H
  413. _32K            equ    00000h
  414. _64K            equ    00001h
  415.  
  416. connection_address    equ    00H
  417. connection_field    equ    0001000000000000B
  418.  
  419. TPE_address        equ    05H
  420. TPE_type_field        equ    0000000000000001B
  421.  
  422. BNC            equ    00000h
  423. AUI            equ    00001h
  424. TPE            equ    00002h
  425.  
  426. int_num_address    equ    00H
  427. int_num_field        equ    1110000000000000B
  428. int_field_shift    equ    13
  429.  
  430. ee_ethernet_add_low    equ    2
  431. ee_ethernet_add_mid    equ    3
  432. ee_ethernet_add_high    equ    4
  433. ee_int                  equ     0
  434. ee_shift                equ     13
  435.  
  436. ;    CPU types
  437. _8088_CPU        equ    00000h
  438. Not_8088_CPU        equ    NOT _8088_CPU
  439.  
  440. ;    Slot Width
  441. slot_width_mask    equ    04h
  442. _16_bit_slot        equ    0000h
  443. _8_bit_slot        equ    0001h
  444.  
  445. _16_bit_override_bit    equ     08h
  446.  
  447.  
  448. ;
  449. ;    BART base port structure
  450. ;
  451. @BARTBasePorts    struc
  452.      @Data_Reg    dw    ?        ;Data Transfer Register.
  453.     @Write_Ptr    dw    ?        ;Write Address Pointer.
  454.     @Read_Ptr    dw    ?        ;Read Address Pointer.
  455.     @CA_Ctrl    db    ?        ;Channel Attention Control.
  456.     @Sel_IRQ    db    ?        ;IRQ Select.
  457.     @SMB_Ptr    dw    ?        ;Shadow Memory Bank Pointer.
  458.             db    ?
  459.     @MEM_Ctrl    db    ?
  460.     @MEM_Page_Ctrl    db    ?
  461.     @Config        db    ?
  462.     @EEPROM_Ctrl    db    ?
  463.     @ID_Port    db    ?
  464. @BARTBasePorts    ends
  465.  
  466.  
  467. @ISR_Ports    struc
  468.             db    0C008h dup(?)
  469.     @SCB_STAT    dw    ?
  470.     @SCB_CMD    dw    ?
  471.     @SCB_CBL    dw    ?
  472.     @SCB_RFA    dw    ?
  473. ;        @SCB_CRCERRS    dw      ?
  474. ;        @SCB_ALNERRS    dw      ?
  475. ;        @SCB_RSCERRS    dw      ?
  476. ;        @SCB_OVRNERRS   dw      ?
  477. @ISR_Ports    ends
  478.  
  479.  
  480. @memory_page_struc    STRUC
  481.             DB    4000H DUP (?)
  482.     @mem_loc_0    DW    ?
  483.     @mem_loc_2    DW    ?
  484.     @mem_loc_4    DW    ?
  485.     @mem_loc_6    DW    ?
  486.     @mem_loc_8    DW    ?
  487.     @mem_loc_10    DW    ?
  488.     @mem_loc_12    DW    ?
  489.     @mem_loc_14    DW    ?
  490.             DB    4000H - 16 DUP (?)
  491.     @mem_loc_16    DW    ?
  492.     @mem_loc_18    DW    ?
  493.     @mem_loc_20    DW    ?
  494.     @mem_loc_22    DW    ?
  495.     @mem_loc_24    DW    ?
  496.     @mem_loc_26    DW    ?
  497.     @mem_loc_28    DW    ?
  498.     @mem_loc_30    DW    ?
  499. @memory_page_struc    ENDS
  500.  
  501. ;
  502. ;
  503. ;    TData Segment
  504. ;
  505. ;    This segment template represents the 64-KB segment that the 82586
  506. ;    can address.  Shared memory can be either 32K or 64K for the BART.
  507. ;    All structures must be quad-word aligned.
  508. ;
  509. ;    Offset    Type of Block    Block Size    Cnt
  510. ;    ------    -------------    ----------    ---
  511. ;    0000h    ISCP        8        1
  512. ;    0008h    SCB        16        1
  513. ;    0020h    CommandBlock    104        1
  514. ;    00E0h    SendBlock(s)    1568        variable
  515. ;    ????h    ReceiveBlock(s)    1568        variable
  516. ;    FFF6h    SCP        10        1
  517. ;
  518.  
  519. TData_64    segment at 0
  520.  
  521. ISCP        ISysConfigPtr  <>
  522. SCB        SystemControlBlock <>
  523.  
  524.         ORG    20H
  525.  
  526. CB        CommandBlock    <>
  527.  
  528. Send_Blocks        DB    SIZE SendBlock * Number_of_Tx_Buffers dup (?)
  529. Receive_Blocks    LABEL    WORD
  530.  
  531.  
  532.     ORG    (0FFFFh - SIZE SCPS + 1) AND 0FFE0H
  533. SCP        LABEL    BYTE
  534.  
  535.     ORG    0FFFFh - SIZE SCPS + 1
  536. THeapTop    LABEL    BYTE            ;Top of available memory
  537.  
  538. end_of_send_blocks = 20h + SIZE CommandBlock + (Number_of_Tx_Buffers * SIZE SendBlock)
  539. num_rx_buf_32k = (07FFFh - SIZE SCPS + 1 - end_of_send_blocks) / (SIZE ReceiveBlock)
  540. num_rx_buf_64k = (0FFFFh - SIZE SCPS + 1 - end_of_send_blocks) / (SIZE ReceiveBlock)
  541.  
  542. TData_64    ENDS
  543.  
  544.  
  545.     public    int_no
  546. int_no        db    3,0,0,0        ;must be four bytes long for get_number.
  547. io_addr        dw    0,0        ; I/O address for card
  548. encoded_int_no    db    ?        ;encoded for bart.
  549.  
  550.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  551. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  552. driver_type    db    255        ;from the packet spec
  553. driver_name    db    'EtherExpress16',0    ;name of the driver.
  554. driver_function    db    26
  555. parameter_list    label    byte
  556.     db    1    ;major rev of packet driver
  557.     db    9    ;minor rev of packet driver
  558.     db    14    ;length of parameter list
  559.     db    EADDR_LEN    ;length of MAC-layer address
  560.     dw    GIANT    ;MTU, including MAC headers
  561.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  562.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  563.     dw    0    ;(# of successive xmits) - 1
  564. int_num    dw    0    ;Interrupt # to hook for post-EOI
  565.             ;processing, 0 == none,
  566. save_err db 0           ;error bits on promiscuous recieve
  567. pro      db 0
  568. pro1     db 0
  569.  
  570.     public    rcv_modes
  571. rcv_modes    dw    7        ;number of receive modes in our table.
  572.         dw    0               ;There is no mode zero
  573.         dw    0
  574.         dw    rcv_mode_2
  575.         dw    rcv_mode_3
  576.         dw    rcv_mode_4    ;haven't set up perfect filtering yet.
  577.         dw    0
  578.         dw    rcv_mode_6
  579.  
  580. ;
  581. ;    82586 Configuration Parameters
  582. ;
  583. config_params            LABEL    WORD
  584. num_config_params        LABEL    BYTE    ;12 BYTEs
  585.                 DB    0CH
  586.  
  587. fifo_limit            LABEL    BYTE    ;Default is 8
  588.                 DB    08H
  589.  
  590. srdy                LABEL    BYTE    ;srdy = 1
  591. save_bad_frame            LABEL    BYTE    ;do not save bad frame
  592.                 DB    40H
  593.  
  594. address_length            LABEL    BYTE    ;6 BYTEs
  595. auto_insert_address        LABEL    BYTE    ;auto insert off (1)
  596. preamble_length            LABEL    BYTE    ;2 BYTEs
  597. internal_loopback        LABEL    BYTE    ;0 = OFF  1 = ON
  598. external_loopback        LABEL    BYTE    ;0 = OFF  1 = ON
  599.                 DB    2EH
  600.  
  601. linear_priority            LABEL    BYTE    ;default is 0
  602. accel_contention_resolution    LABEL    BYTE    ;default is 0
  603. exp_backoff_method        LABEL    BYTE    ;0 = 802.3  1 = Alternate
  604.                 DB    00H
  605.  
  606. interframe_spacing        LABEL    BYTE    ;default is 60H (96 bits)
  607.                 DB    60H
  608.  
  609. slot_time_low            LABEL    BYTE    ;0
  610.                 DB    00H
  611.  
  612. slot_time_high            LABEL    BYTE    ;2
  613. retry_num            LABEL    BYTE    ;15
  614.                 DB    0F2H
  615.  
  616. promiscuous_mode        LABEL    BYTE    ;0 = OFF  1 = ON
  617. broadcast_disable        LABEL    BYTE    ;0 = OFF  1 = ON
  618. encode_decode            LABEL    BYTE    ;0 = NRZ  1 = MANCHESTER
  619. transmit_on_no_carrier        LABEL    BYTE    ;0 = STOP 1 = CONTINUE
  620. no_crc_insertion        LABEL    BYTE    ;0 = OFF  1 = ON
  621. crc_type            LABEL    BYTE    ;0 = 32 bit autodin II
  622.                         ;1 = 16 bit CCITT
  623. bit_stuffing            LABEL    BYTE    ;0 = 802.3  1 = HDLC
  624. padding                LABEL    BYTE    ;0 = OFF  1 = ON
  625.                 DB    00H
  626.  
  627. carrier_sense_filter        LABEL    BYTE    ;0 = OFF  1 = 0N
  628. carrier_sense_source        LABEL    BYTE    ;0 = external  1 = internal
  629. collision_detect_filter        LABEL    BYTE    ;default = 0
  630. collision_detect_source        LABEL    BYTE    ;0 = external  1 = internal
  631.                 DB    00H
  632.  
  633. min_frame_length        LABEL    BYTE    ;60 BYTEs
  634.                 DB    60
  635.                 DB    00H    ;undefined
  636.  
  637.  
  638. RxBufferCount            dw    ?
  639. TxBufferCount            dw    ?
  640.  
  641. Receive_Head            DW    ?
  642. Receive_Tail            DW    ?
  643.  
  644. our_type    dw    8 dup(?)
  645.  
  646. is_186        db    0        ;=0 if 808[68], =1 if 80[123]86.
  647. rom_address    db    EADDR_LEN dup(?)
  648.  
  649.     include    io16.asm
  650.  
  651.     public    as_send_pkt
  652. ; The Asynchronous Transmit Packet routine.
  653. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  654. ;   interrupts possibly enabled.
  655. ; Exit with nc if ok, or else cy if error, dh set to error number.
  656. ;   es:di and interrupt enable flag preserved on exit.
  657. as_send_pkt:
  658.     ret
  659.  
  660.     public    drop_pkt
  661. ; Drop a packet from the queue.
  662. ; Enter with es:di -> iocb.
  663. drop_pkt:
  664.     assume    ds:nothing
  665.     ret
  666.  
  667.     public    xmit
  668. ; Process a transmit interrupt with the least possible latency to achieve
  669. ;   back-to-back packet transmissions.
  670. ; May only use ax and dx.
  671. xmit:
  672.     assume    ds:nothing
  673.     ret
  674.  
  675.  
  676.     public    send_pkt
  677. send_pkt:
  678. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  679. ;  (only if the high-performance bit is set in driver_function)
  680. ;enter with ds:si -> packet, cx = packet length.
  681. ;if we're a high-performance driver, es:di -> upcall.
  682. ;exit with nc if ok, or else cy if error, dh set to error number.
  683.     assume    ds:nothing
  684.         cmp     pro1,1
  685.         je      no_size_check1
  686.  
  687.     cmp    cx,GIANT        ; Is this packet too large?
  688.     jna    no_size_check1
  689.         jmp     send_pkt_toobig
  690.  
  691. no_size_check1:
  692.  
  693.     push    bp
  694.     mov    bp,io_addr
  695.  
  696.         disable_board_ints
  697.         cmd_clear               ; wait for command processor to clear
  698.  
  699.         cmp     pro1,1           ; on pro drive do not ajust size
  700.         je      oklen
  701.  
  702.     cmp    cx,RUNT        ; minimum length for Ether
  703.     jae    oklen
  704.     mov    cx,RUNT        ; make sure size at least RUNT
  705. oklen:
  706.     inc    cx        ;round size up to next even number.
  707.     and    cx,not 1
  708. ;
  709. ; Set SMB pointer to the transmit buffer.
  710. ;
  711.     lea    dx,[BP].@SMB_Ptr
  712.     mov    ax,offset send_blocks
  713.     out    dx,ax
  714. ;
  715. ; Write evenized, padded packet length (>= RUNT bytes) to 586 TBD byte
  716. ; count field.  OR on the End of Frame bit.
  717. ;
  718.     lea    dx,[BP].@TBD_ByteCount
  719.     mov    ax,cx
  720.     or    ah,byte_BIT_EOF
  721.     out    dx,ax
  722. ;
  723. ; Set the TxCB command field for transmit.  Also set the EL bit (End of List).
  724. ;
  725.     lea    dx, [BP].@TxCB_Command
  726.     mov    ax, BIT_EL+GA_Transmit
  727.     out    dx, ax
  728. ;
  729. ; Set write pointer to the data buffer for current send block.  Also
  730. ; set DX to the data register.
  731. ;
  732.     lea    dx, [BP].@Write_Ptr
  733.     mov    ax, offset send_blocks
  734.     add    ax, offset TB_Data
  735.     out    dx, ax
  736.     mov    dx, bp            ;@Data_Reg
  737.  
  738.     call    repoutsw
  739. ;.286
  740. ;        rep outsb
  741.  
  742. send_continue:
  743. ;
  744. ; Set the SCBs command block pointer to this send packet.
  745. ;
  746.     lea    dx, [BP].@SCB_CBL
  747.     mov    ax, offset send_blocks
  748.     out    dx, ax
  749.  
  750. ;
  751. ; Set the SCB command to start the command unit.
  752. ;
  753.     lea    dx, [BP].@SCB_CMD
  754.     mov    ax, CUC_START
  755.     out    dx, ax
  756.     issue_ca
  757.  
  758.         cmd_clear                         ; wait for frame transmit to start
  759.      lea    dx,[BP].@SMB_Ptr
  760.      mov    ax,offset send_blocks
  761.      out    dx,ax
  762.  
  763.         lea     dx,[BP].@TxCB_status
  764. transmiting:
  765.         in      ax,dx
  766.  
  767.         test    ax,BIT_C                ; check status of transmit
  768.         jz      transmiting
  769.  
  770.         test    ax,BIT_OK               ; how was the x-mit
  771.         jnz     tx_ok
  772.  
  773.         enable_board_ints
  774.         pop     bp
  775.         mov     dh,255
  776.         jmp     tx_bad
  777.  
  778. tx_ok:
  779.         enable_board_ints
  780.  
  781.     pop    bp
  782.  
  783.     clc
  784.     ret
  785.  
  786. send_pkt_toobig:
  787.     mov    dh,NO_SPACE
  788. tx_bad:
  789.     stc
  790.     ret
  791.  
  792.  
  793. ;    ReadTickCounter
  794. ;
  795. ;    Read the 16 bit timer tick count register (system board timer 0).
  796. ;    The count register decrements by 2 (even numbers) every 838ns.
  797. ;
  798. ;    Assumes:    Interrupts disabled
  799. ;
  800. ;    Returns:    AX with the current count
  801. ;            Interrupts disabled
  802.  
  803. ReadTickCounter:
  804.  
  805.     push    dx
  806.  
  807.     mov    dx, 43h                ;Command 8254 timer to latch
  808.     xor    al, al                ; T0's current count
  809.     out    dx, al
  810.  
  811.     mov    dx, 40h                ;read the latched count
  812.     in    al, dx                ; LSB first
  813.     mov    ah, al
  814.     in    al, dx                ; MSB next
  815.     xchg    al, ah                ;put count in proper order
  816.  
  817.     pop    dx
  818.     ret
  819.  
  820.  
  821.     public    get_address
  822. get_address:
  823. ;get the address of the interface.
  824. ;enter with es:di -> place to get the address, cx = size of address buffer.
  825. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  826. ; Give caller the one currently in the 8390, not necessarily the one in PROM.
  827.     assume ds:code
  828.     cmp cx,    EADDR_LEN        ; Caller wants a reasonable length?
  829.     jb    get_addr_x        ; No, fail.
  830.     mov cx,    EADDR_LEN        ; Move one ethernet address from our copy
  831.     mov si, offset rom_address    ; Copy from most recent setting
  832.     rep     movsb
  833.     mov cx,    EADDR_LEN        ; Tell caller how many bytes we fed him
  834.     clc                ; Carry off says success
  835.     ret
  836. get_addr_x:
  837.     stc                ; Tell caller our addr is too big for him
  838.     ret
  839.  
  840.  
  841.     public    set_address
  842. set_address:
  843. ;enter with ds:si -> Ethernet address, CX = length of address.
  844. ;exit with nc if okay, or cy, dh=error if any errors.
  845.     assume    ds:nothing
  846.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  847.     je    set_address_4
  848.     mov    dh,BAD_ADDRESS
  849.     stc
  850.     jmp    short set_address_done
  851. set_address_4:
  852.         push    bp
  853.     push    ds
  854.     push    si
  855.  
  856.     push    cs
  857.     pop    ds
  858. ;
  859. ; Set up individual address command block.
  860. ;
  861.         mov     bp,ds:io_addr
  862.         cmd_clear
  863.     mov    bx, BIT_EL+GA_IA_Setup
  864.     call    setup_command_block
  865.  
  866.     pop    si
  867.     pop    ds
  868.  
  869. ;
  870. ; Copy individual address command parameters to individual address
  871. ; command block.
  872. ;
  873.     mov    cx, EADDR_LEN/2
  874. move_node_address:
  875.     lodsw
  876.     out    dx, ax
  877.     loop    move_node_address
  878.  
  879. ;
  880. ; Signal 586 to execute individual address command.
  881. ;
  882.     mov    ax, CUC_Start
  883.     mov    bx, BIT_CNA
  884.     call    issue_command
  885.  
  886.     lea    dx, [bp].@SMB_Ptr        ;Move IO frame to the command
  887.     mov    ax, offset cb            ; command block.
  888.     out    dx, ax
  889.  
  890.         lea     dx,[BP].@CB_Status
  891. working1:
  892.         in      ax,dx
  893.  
  894.         test    ax,BIT_C                ; check status of set_ia
  895.         jz      working1
  896.  
  897.         test    ax,BIT_OK
  898.         jnz     set_ok
  899.         pop     bp
  900.         stc
  901.         jmp     set_address_done
  902.  
  903. set_ok:
  904.         mov     cx,5000h  ; on 486's if we do not delay this command does not work
  905. set1:
  906.         mov     bx,cx
  907.         mov     ax,[bx]
  908.         loop    set1    ; just for delay
  909.  
  910.     mov    cx,EADDR_LEN        ;return their address length.
  911.     clc
  912.         pop     bp
  913. set_address_done:
  914.     push    cs
  915.     pop    ds
  916.     assume    ds:code
  917.     ret
  918.  
  919.  
  920. rcv_mode_2:
  921.     and    promiscuous_mode,not 3
  922.     or    promiscuous_mode,2    ;disable broadcasts.
  923.     mov    min_frame_length,60
  924.         and     save_bad_frame,not 80h
  925.         mov     pro,0
  926.     jmp    short configure_command
  927. rcv_mode_4:
  928. rcv_mode_3:
  929.     and    promiscuous_mode,not 3    ;clear promiscuous mode.
  930.     mov    min_frame_length,60
  931.         and     save_bad_frame,not 80h
  932.         mov     pro,0
  933.     jmp    short configure_command
  934. rcv_mode_6:
  935.     and    promiscuous_mode,not 3
  936.     or    promiscuous_mode,1    ;set promiscuous mode.
  937.     mov    min_frame_length,60    ;allow runt. but let it come in as a bad frame
  938.         or      save_bad_frame,80h      ; yes we want bad frames here
  939.         mov     pro,1
  940.         mov     pro1,1
  941. ;
  942. configure_command:
  943.         mov     bp,io_addr
  944. ;
  945. ; Set up configure command block.
  946. ;
  947.     mov    bx, bit_el + GA_Configure    ;Set command block for a
  948.     call    setup_command_block        ; configure command. BIT_EL
  949.                         ; means last command.
  950. ;
  951. ; Copy configure command parameters to configure command block.
  952. ;
  953.     mov    si,offset config_params        ;Set DS:SI to parameters and
  954.     mov    cx, 6                ; copy them to the command
  955.  
  956. move_config_params:
  957.  
  958.     lodsw
  959.     out    dx, ax
  960.     loop    move_config_params
  961. ;
  962. ; Signal 586 to execute configure command.
  963. ;
  964.     mov    ax, CUC_Start
  965.     mov    bx, BIT_CNA
  966.     call    issue_command
  967.     clc
  968.     ret
  969.  
  970.  
  971. ;*****************************************************************
  972. ; TDR cable tester
  973. ; enter with es:di pointing to time int
  974. ;*****************************************************************
  975.  
  976.         public do_tdr
  977. do_tdr:
  978.         push    bp
  979.         push    es
  980.         push    di
  981.         mov     bp,io_addr
  982. ;
  983. ; Set up configure command block.
  984. ;
  985.     mov    bx, bit_el + GA_TDR         ;Set command block for a
  986.     call    setup_command_block        ; TDR command. BIT_EL
  987.                         ; means last command.
  988. ; Signal 586 to execute configure command.
  989. ;
  990.     mov    ax, CUC_Start
  991.     mov    bx, BIT_CNA
  992.     call    issue_command
  993.  
  994.     lea    dx, [bp].@SMB_Ptr        ;Move IO frame to the command
  995.     mov    ax, offset cb            ; command block.
  996.     out    dx, ax
  997.  
  998.         lea     dx,[BP].@CB_Status
  999. working:
  1000.         in      ax,dx
  1001.  
  1002.         test    ax,BIT_C                ; check status of transmit
  1003.         jz      working
  1004.  
  1005.         lea     dx,[bp].@CB_Parm0
  1006.         in      ax,dx
  1007.  
  1008.         pop     di
  1009.         pop     es
  1010.         pop     bp
  1011.  
  1012.         test    ax,LNK_OK
  1013.         jz      tdr_bad_cable
  1014.     clc
  1015.     ret
  1016.  
  1017. tdr_bad_cable:
  1018.  
  1019.         push    ax
  1020.         and     ax,TDR_TIME
  1021.         stosw                      ; store time
  1022.         pop     ax
  1023.  
  1024.         mov     cl,12
  1025.         shr     ax,cl
  1026.         and     ax,7
  1027.         mov     dh,al
  1028.  
  1029.         stc
  1030.         ret
  1031.  
  1032.  
  1033. ;
  1034. ;    BX = 586 command word
  1035. ;
  1036. setup_command_block:
  1037.  
  1038. ;
  1039. ; Setup command block's command, status, and link fields.
  1040. ;
  1041.     lea    dx, [bp].@SMB_Ptr        ;Move IO frame to the command
  1042.     mov    ax, offset cb            ; command block.
  1043.     out    dx, ax
  1044.  
  1045.     lea    dx, [bp].@CB_link        ;Set command block's link to
  1046.     out    dx, ax                ; itself.
  1047.  
  1048.     lea    dx, [bp].@SCB_CBL        ;Point SCB command list
  1049.     out    dx, ax                ; pointer to command block.
  1050.  
  1051.     lea    dx, [bp].@CB_command        ;Set command block's command
  1052.     mov    ax, bx                ; word to value passed in
  1053.     out    dx, ax                ; BX.
  1054.  
  1055. ;
  1056. ; Return with the write pointer set to the command block parameter
  1057. ; offset.
  1058. ;
  1059.     lea    dx, [bp].@Write_Ptr        ;Set write pointer to command
  1060.     lea    ax, CB.CB_Param0        ; parameter field.
  1061.     out    dx, ax
  1062.  
  1063.     mov    dx, bp            ;@Data_Reg
  1064.     ret
  1065.  
  1066.  
  1067. ;
  1068. ; Wait for 586 command register to be clear (  1 millisecond max)
  1069. ; Issue command
  1070. ; Wait for command to complete              (500 milliseconds max)
  1071. ; Acknowledge command complete
  1072. ;
  1073. ;
  1074. issue_command:
  1075.  
  1076. ;
  1077. ; Make sure 586 command in SCB is clear.
  1078. ;
  1079.     mov    cx, ax
  1080.     cmd_clear
  1081.     jnz    issue_command_error_exit
  1082.     mov    ax, cx
  1083. ;
  1084. ; Put command code in AX into SCB command register and signal the
  1085. ; 586 to look at it.  The cmd_clear macro leaves DX pointing to
  1086. ; the SCB command register.
  1087. ;
  1088.     out    dx, ax
  1089.     issue_ca
  1090.  
  1091. wait_for_commad_status_outer_loop:
  1092. ;
  1093. ; Wait here for 586 to complete the command.  586 should never take
  1094. ; more than 500 Milliseconds to complete a command.
  1095. ;
  1096.     call    readtickcounter
  1097.     mov    cx, ax
  1098.     lea    dx, [bp].@SCB_STAT
  1099.  
  1100. wait_for_commad_status:
  1101.  
  1102.     in    ax, dx
  1103.     cmp    ax, bx
  1104.     je    acknowledge_command_complete
  1105.  
  1106.     call    readtickcounter
  1107.     neg    ax
  1108.     add    ax, cx
  1109.     cmp    ax, ten_mils
  1110.     jb    wait_for_commad_status
  1111.  
  1112. _586_command_error:
  1113. ;
  1114. ; Signal error by pointing AX to error message, and setting
  1115. ; condition codes.
  1116. ;
  1117.     MOV    AX, OFFSET _586_not_responding_msg
  1118.     OR    AX, AX
  1119.  
  1120. issue_command_error_exit:
  1121.  
  1122.     RET
  1123.  
  1124. acknowledge_command_complete:
  1125. ;
  1126. ; Tell the 586 that we know its done by copying the status back to
  1127. ; the command register's acknowledge fields.  BX has status.
  1128. ;
  1129.     lea    dx, [bp].@SCB_CMD
  1130.     out    dx, ax
  1131.     issue_ca
  1132. ;
  1133. ; Signal no error.
  1134. ;
  1135.     xor    ax, ax
  1136.     ret
  1137.  
  1138.  
  1139.     public    set_multicast_list
  1140. set_multicast_list:
  1141. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  1142. ;return nc if we set all of them, or cy,dh=error if we didn't.
  1143.     mov    dh,NO_MULTICAST
  1144.     stc
  1145.     ret
  1146.  
  1147.  
  1148.     public    terminate
  1149. terminate:
  1150.         push    bp
  1151.         mov     bp,io_addr
  1152.  
  1153.         cmd_clear                  ; wait until last command is done processing
  1154.  
  1155.         disable_board_ints         ; shut off board ints
  1156.  
  1157.         lea     dx,[bp].@SCB_CMD
  1158.     mov    ax, RUC_SUSPEND    ; suspend recieve unit
  1159.     out    dx, ax
  1160.     issue_ca
  1161.  
  1162.         pop     bp                 ; now ok to un-hook interrupts and release
  1163.     ret                        ; driver
  1164.  
  1165.     public    reset_interface
  1166. reset_interface:
  1167. ;reset the interface.
  1168.     assume    ds:code
  1169.     ret
  1170.  
  1171.  
  1172. ;called when we want to determine what to do with a received packet.
  1173. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  1174.     extrn    recv_find: near
  1175.  
  1176. ;called after we have copied the packet into the buffer.
  1177. ;enter with ds:si ->the packet, cx = length of the packet.
  1178.     extrn    recv_copy: near
  1179.  
  1180.     extrn    count_in_err: near
  1181.     extrn    count_out_err: near
  1182. ;        extrn   resource_err_in:word
  1183.  
  1184.     public    recv
  1185. recv:
  1186. ;called from the recv isr.  All registers have been saved, and ds=cs.
  1187. ;Upon exit, the interrupt will be acknowledged.
  1188.     assume    ds:code
  1189. ;
  1190. ; Set BP to the base IO address of bart.  Also disable barts ability
  1191. ; to generate interrupts.
  1192. ;
  1193.     mov    bp,io_addr
  1194.     disable_board_ints
  1195. ;
  1196. ; Make sure that command unit is clear before reading the status.
  1197. ;
  1198.     cmd_clear
  1199. ;
  1200. ; Get the SCB status to see why bart interrupted us.  Also need to
  1201. ; copy the status back to the command word to acknowledge the 586
  1202. ; interrupt.  Issue channel attention to get the 586 to realize the
  1203. ; interrupt aknowledge.
  1204. ;
  1205. ;        lea     dx, [bp].@SCB_RSCERRS
  1206. ;        in      ax,dx
  1207. ;        mov     word ptr resource_err_in,ax
  1208. ;        lea     dx, [bp].@SCB_OVRNERRS
  1209. ;        in      ax,dx
  1210. ;        add     word ptr resource_err_in,ax
  1211.  
  1212.     lea    dx, [bp].@SCB_STAT
  1213.     in    ax, dx
  1214.     and    ax, ACK_INT_MASK
  1215.  
  1216.     lea    dx, [bp].@SCB_CMD
  1217.     out    dx, ax
  1218.     issue_ca                ; AX is not changed.
  1219. ;
  1220. ; Check for frame receive status.  Jump if no frames received,
  1221. ; otherwise processes the receive.
  1222. ;
  1223.     test    AX, BIT_FR OR BIT_RNR
  1224.     jz    ExitDriverISR
  1225.     call    ProcessRx
  1226. ExitDriverISR:
  1227. ;
  1228. ; Here if there was a bad receive status.  Make sure the receive unit
  1229. ; of the 586 is running.  Read in the SCB status and jump if we need
  1230. ; to restart the receive unit.  We choose to have the jump to restart
  1231. ; the RU since most of the time we will not need to do this.  This
  1232. ; saves cycle times when exiting without a restart.
  1233. ;
  1234.     lea    dx, [bp].@SCB_STAT
  1235.     in    ax, dx
  1236.     test    ax, READY
  1237.     jz    restart_RU
  1238.  
  1239. drvisr_continue:
  1240.     enable_board_ints
  1241.     ret
  1242.  
  1243.  
  1244. restart_RU:
  1245. deb 160
  1246. ;
  1247. ; Need to restart the receive unit of the 586.  Set the SCB pointer to
  1248. ; the receive frame area.
  1249. ;
  1250.     lea    dx, [bp].@SCB_RFA
  1251.     mov    ax, Receive_Head
  1252.     out    dx, ax
  1253. ;
  1254. ; Make sure 586 is in a state to accept a command.
  1255. ;
  1256.     cmd_clear
  1257. ;
  1258. ; Put the receive unit start command into the SCB command word and
  1259. ; issue the channel attention.
  1260. ;
  1261. ; NOTE: cmd_clear macro leaves DX pointing to the SCB command word.
  1262. ;
  1263. ;    lea    dx, [bp].@SCB_CMD
  1264.     mov    ax, RUC_START
  1265.     out    dx, ax
  1266.     issue_ca
  1267.     jmp    drvisr_continue
  1268.  
  1269.  
  1270. ProcessRx:
  1271.  
  1272. ;
  1273. ; Prime the pump that services receives by setting AX to the receive
  1274. ; head.  There could be over 30 packets received.
  1275. ;
  1276. deb 1
  1277.     mov    ax,Receive_Head
  1278.  
  1279. CheckNextReceiveStatus:
  1280.  
  1281. ;
  1282. ; Save receive head pointer in BX.  BX should not be altered during
  1283. ; this loop.
  1284. ;
  1285.     mov    bx, ax
  1286. ;
  1287. ; Set SMB pointer to the top of the receive frame.
  1288. ;
  1289.     lea    dx, [bp].@SMB_Ptr
  1290.     out    dx, ax
  1291. ;
  1292. ; Get the status for this receive frame.  Check to make sure that
  1293. ; it completed with no errors.  If not, then jump to check the
  1294. ; 586 receive unit.
  1295. ;
  1296.     lea    dx, [bp].@FD_Status
  1297.     in    ax, dx
  1298.  
  1299.         mov     save_err,1   ; be sure we done accdently report an error
  1300.  
  1301.     test    ax, BIT_C   ; command compleat
  1302.     jz    PRx_no
  1303.         test    ax,BIT_OK  ; good frame
  1304.         jnz     ProcessRx_1
  1305.  
  1306.         call    count_in_err
  1307.         mov     save_err,0
  1308.         cmp     pro,1
  1309.         je      PRx_bad                ; if not in pro-mode lose bad frames and inc error
  1310. ;       call    count_in_err
  1311.         jmp     recv_isr_9
  1312. PRx_no:
  1313.     ret
  1314.  
  1315. PRx_bad:
  1316.        mov     dh,0
  1317.        test    ax,BIT_S7
  1318.        jz      PR_no_frag
  1319.        or      dh,2
  1320. PR_no_frag:
  1321.        test    ax,BIT_S11
  1322.        jz      PR_no_crc
  1323.        or      dh,4
  1324. PR_no_crc:
  1325.        test    ax,BIT_S10
  1326.        jz      PR_no_align
  1327.        or      dh,8
  1328. PR_no_align:
  1329.        test    ax,BIT_S8
  1330.        jz      PR_no_dma
  1331.        or      dh,16
  1332. PR_no_dma:
  1333.        test    ax,BIT_S9
  1334.        jz      PR_no_ru
  1335.        or      dh,32
  1336. PR_no_ru:
  1337.  
  1338.        mov     save_err,dh
  1339.        jmp     ProcessRx_1
  1340.  
  1341. ProcessRx_1:
  1342. deb 2
  1343. ;
  1344. ; Set the read pointer to access the LengthTypeField.
  1345. ;
  1346. ; NOTE: BX was set to receive head at the beginning of this
  1347. ;       procedure.
  1348. ;
  1349.     lea    dx, [bp].@Read_Ptr
  1350.     lea    ax, [BX].IPX_LengthTypeField
  1351.     out    dx, ax
  1352.     mov    dx, bp            ;@Data_Reg
  1353.  
  1354.     mov    ax,cs
  1355.     mov    es,ax
  1356.     mov    di,offset our_type
  1357.     mov    cx,8
  1358.     call    repinsw
  1359. ;.286
  1360. ;        rep insb
  1361.  
  1362. ;
  1363. ; Get the packet size from the 586 data structure.
  1364. ;
  1365.     lea    dx, [bp].@RBD_ByteCount
  1366.     in    ax, dx
  1367.     and    ah, 3fh
  1368.     mov    cx, ax
  1369.  
  1370.     mov    di,offset our_type
  1371.  
  1372.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  1373.     mov    ax, es:[di]
  1374.     xchg    ah, al
  1375.     cmp     ax, 1518
  1376.     ja    BlueBookPacket
  1377.     inc    di            ;set di to 802.2 header
  1378.     inc    di
  1379.     mov    dl, IEEE8023
  1380. BlueBookPacket:
  1381. deb 3
  1382.     push    bx
  1383.         push    cx                      ; for some reison recv_find trashes cx
  1384.         mov     dh,save_err
  1385.     call    recv_find
  1386.         mov    bp,cs:io_addr              ; just in case
  1387.         pop     cx
  1388.     pop    bx
  1389.  
  1390.     mov    ax,es            ;is this pointer null?
  1391.     or    ax,di
  1392.     je    recv_isr_9        ;yes - just free the frame.
  1393.     push    es            ;remember where the buffer pointer is.
  1394.     push    di
  1395.     push    cx
  1396. deb 4
  1397. ;
  1398. ; Set the read pointer to access the packet.
  1399. ;
  1400. ; NOTE: BX was set to receive head at the beginning of this
  1401. ;       procedure.
  1402. ;
  1403.     lea    dx, [bp].@Read_Ptr
  1404.     lea    ax, [BX].IPX_DestAddr_HIGH
  1405.     out    dx, ax
  1406.     mov    dx, bp            ;@Data_Reg
  1407. ;
  1408. ; Now read the packet into es:di
  1409. ;
  1410.     call    repinsw
  1411. ;        rep insb
  1412.  
  1413.     pop    cx
  1414.     pop    si
  1415.     pop    ds
  1416.     assume    ds:nothing
  1417.     call    recv_copy        ;tell them that we copied it.
  1418.     mov    ax,cs            ;restore our ds.
  1419.     mov    ds,ax
  1420.     assume    ds:code
  1421.  
  1422.         mov    bp,io_addr              ; just in case
  1423. deb 5
  1424. recv_isr_9:
  1425.  
  1426. ;
  1427. ; Clear the current receive frames status.
  1428. ;
  1429.     lea    dx, [bp].@FD_Status
  1430.     xor    ax, ax
  1431.     out    dx, ax
  1432. ;
  1433. ; Set the end of list bit for the current receive frame.
  1434. ;
  1435.     lea    dx, [bp].@FD_command
  1436.     mov    ax, BIT_EL
  1437.     out    dx, ax
  1438. ;
  1439. ; Read in the pointer to the next receive frame.
  1440. ;
  1441.     lea    dx, [bp].@FD_Link
  1442.     in    ax, dx
  1443. ;
  1444. ; Update our local pointer to the receive resources:
  1445. ;
  1446. ; Receive_tail <-- Receive head
  1447. ; Receive_head <-- next receive frame.
  1448. ;
  1449.     mov    BX, Receive_Head
  1450.     mov    Receive_Tail, BX
  1451.     mov    Receive_Head, AX
  1452.     mov    cx, ax
  1453. ;
  1454. ; Clear previous receive frame descriptors end of list bit to free up
  1455. ; a receive resource.  We do this by moving the write pointer to the
  1456. ; the command word in the previous receive frame and then writing a
  1457. ; zero to it.
  1458. ;
  1459.     lea    dx, [bp].@Write_Ptr
  1460.     lea    ax, [bx].FD_command
  1461.     out    dx, ax
  1462.  
  1463.     mov    dx, bp            ;@Data_Reg
  1464.     xor    ax, ax
  1465.     out    dx, ax
  1466. ;
  1467. ; Check for another receive frame.
  1468. ;
  1469.     mov    ax, cx
  1470.     jmp    CheckNextReceiveStatus
  1471.  
  1472.  
  1473.  
  1474.     public    recv_exiting
  1475. recv_exiting:
  1476. ;called from the recv isr after interrupts have been acknowledged.
  1477. ;Only ds and ax have been saved.
  1478.     assume    ds:nothing
  1479.     ret
  1480.  
  1481. ; This procedure is called from the cmd_clear macro after the macro determines
  1482. ; that we must wait for a command to clear.
  1483. ;
  1484. ;     MUST NOT TRASH CX OR THE ISSUE_COMMAND PROCEDURE WILL FAIL.
  1485. ;
  1486. cmd_wait:
  1487. ;enter with dx -> SCB_CMD
  1488. ;exit with nc if it cleared in one millisecond, cy if not.
  1489.  
  1490.     call    readtickcounter            ;Reference clock.  die after
  1491.     mov    bx, ax                ; 1 ms.
  1492.  
  1493. wait_cmd_clear:
  1494.  
  1495.     in    ax, dx                ;Read SCB command
  1496.     or    ax, ax                ;Wait for command accepted
  1497.     jz    exit
  1498.  
  1499.     call    readtickcounter
  1500.     neg    ax
  1501.     add    ax, bx
  1502.  
  1503.     cmp    ax, one_mil
  1504.     jb    wait_cmd_clear
  1505.  
  1506.     stc
  1507. exit:
  1508.     ret
  1509.  
  1510.  
  1511. ;any code after this will not be kept after initialization.
  1512. end_resident    label    byte
  1513.  
  1514.  
  1515.     public    usage_msg
  1516. usage_msg    db    "usage: exp16 [-n] [-d] [-w] <packet_int_no> [<io_addr>]",CR,LF,'$'
  1517.  
  1518.     public    copyright_msg
  1519. copyright_msg    db    "Packet driver for the Intel EtherExpress 16, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  1520.                 db      "Copyright Intel Corp",CR,LF,'$'
  1521. using_186_msg    db    "Using 80[123]86 I/O instructions.",CR,LF,'$'
  1522.  
  1523. int_no_name    db    "Interrupt number ",'$'
  1524. io_addr_name    db    "I/O port ",'$'
  1525.  
  1526.     extrn    set_recv_isr: near
  1527.  
  1528. ;enter with si -> argument string, di -> dword to store.
  1529. ;if there is no number, don't change the number.
  1530.     extrn    get_number: near
  1531.  
  1532. ;enter with dx -> argument string, di -> dword to print.
  1533.     extrn    print_number: near
  1534.  
  1535.  
  1536.     public    etopen
  1537. etopen:
  1538. ;initialize the driver.
  1539.     assume    ds:code
  1540. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  1541. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  1542.     mov    cl,33
  1543.     mov    ax,0ffffh
  1544.     shl    ax,cl
  1545.     jz    not_186
  1546.     mov    is_186,1
  1547.     mov    dx,offset using_186_msg
  1548.     mov    ah,9
  1549.     int    21h
  1550. not_186:
  1551.  
  1552. ;
  1553. ; Get board information (Node address, etc.).  Returns with BP
  1554. ; set to the board IO base address (if not errors).
  1555. ;
  1556.     call    get_system_info
  1557.     jnz    driver_init_error_exit
  1558.  
  1559.     disable_board_ints
  1560. ;
  1561. ; If they're in an 8-bit slot, make sure that they aren't using the slave PIC.
  1562. ;
  1563.     cmp    _16_not_8_bit_slot,0    ;are they using a 16-bit slot?
  1564.     jne    check_config_exit    ;yes -- cool.
  1565.  
  1566.     mov    dx,offset irq_config_error
  1567.     cmp    int_no, 9        ;no - don't let them use the upper IRQs.
  1568.     jae    driver_init_error_exit
  1569. check_config_exit:
  1570.  
  1571. ;
  1572. ; Initialize the 586 and the 586 data structures.
  1573. ;
  1574.     call    init_586
  1575.     jnz    driver_init_error_exit
  1576.  
  1577. ; test iochrdy
  1578.         call    iochrdy_test
  1579. ;
  1580. ; Set up Interrupt line, start the receive unit, and Enable barts interrupt.
  1581. ;
  1582.     call    set_recv_isr
  1583.     call    ru_start
  1584.     enable_board_ints
  1585.  
  1586.     mov    al, int_no        ; Get board's interrupt vector
  1587.     add    al, 8
  1588.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1589.     jb    set_int_num        ; No.
  1590.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1591. set_int_num:
  1592.     xor    ah, ah            ; Clear high byte
  1593.     mov    int_num, ax        ; Set parameter_list int num.
  1594.  
  1595.     mov    dx,offset end_resident
  1596.     clc
  1597.     ret
  1598.  
  1599. driver_init_error_exit:
  1600.     stc
  1601.     ret
  1602.  
  1603.  
  1604. ; int number to IRQ translate table.
  1605. IRQ_xlat_table    LABEL    BYTE
  1606.         DB    00H            ;IRQ 0    Invalid IRQ
  1607.         DB    00H            ;IRQ 1    Invalid IRQ
  1608.         DB    01H            ;IRQ 2      Valid IRQ
  1609.         DB    02H            ;IRQ 3       Valid IRQ
  1610.         DB    03H            ;IRQ 4       Valid IRQ
  1611.         DB    04H            ;IRQ 5       Valid IRQ
  1612.         DB    00H            ;IRQ 6     Invalid IRQ
  1613.         DB    00H            ;IRQ 7     Invalid IRQ
  1614.         DB    00H            ;IRQ 8     Invalid IRQ
  1615.         DB    01H            ;IRQ 9      Valid IRQ
  1616.         DB    05H            ;IRQ 10   Valid IRQ
  1617.         DB    06H            ;IRQ 11   Valid IRQ
  1618. max_IRQ        EQU    $-IRQ_xlat_table
  1619.  
  1620. io_addresses label word
  1621.                dw  300h,310h,320h,330h,340h,350h,360h,370h
  1622.                dw  200h,210h,220h,230h,240h,250h,260h,270h
  1623.                dw  0
  1624.  
  1625.     public    parse_args
  1626. parse_args:
  1627. ;    mov    di,offset int_no
  1628. ;    call    get_number
  1629.     mov    di,offset io_addr
  1630.     call    get_number
  1631.  
  1632. ;    mov    al,int_no        ;ensure that it's in our table.
  1633. ;    cmp    al,max_IRQ
  1634. ;    ja    get_encoded_irq_error_exit
  1635. ;
  1636. ;    mov    bx,offset irq_xlat_table ;encode it into the number bart wants.
  1637. ;    xlat
  1638. ;
  1639. ;    or    al, al            ;if zero, bart doesn't want it.
  1640. ;    je    get_encoded_irq_error_exit
  1641. ;    mov    encoded_int_no,al
  1642. ;
  1643.     clc
  1644.     ret
  1645.  
  1646. ;get_encoded_irq_error_exit:
  1647. ;    stc
  1648. ;    ret
  1649.  
  1650. bnc_connector_msg    db    "Configured for the BNC connector",CR,LF,'$'
  1651. aui_connector_msg    db    "Configured for the AUI connector",CR,LF,'$'
  1652. tpe_connector_msg    db    "Configured for the twisted-pair connector",CR,LF,'$'
  1653.  
  1654. _8_bit_slot_msg        db    "The board is in an 8-bit slot",CR,LF,'$'
  1655. _16_bit_slot_msg    db    "The board is in a 16-bit slot",CR,LF,'$'
  1656.  
  1657. badset_msg              db      "Set Address Command Failed",CR,LF,'$'
  1658.  
  1659.  
  1660.     public    print_parameters
  1661. print_parameters:
  1662.     mov    di,offset int_no
  1663.     mov    dx,offset int_no_name
  1664.     call    print_number
  1665.     mov    di,offset io_addr
  1666.     mov    dx,offset io_addr_name
  1667.     call    print_number
  1668.  
  1669.     mov    dx,offset bnc_connector_msg    ;print the connection type.
  1670.     cmp    connection_type,BNC
  1671.     je    print_parameters_1
  1672.     mov    dx,offset aui_connector_msg
  1673.     cmp    connection_type,AUI
  1674.     je    print_parameters_1
  1675.     mov    dx,offset tpe_connector_msg
  1676. print_parameters_1:
  1677.     mov    ah,9
  1678.     int    21h
  1679.  
  1680.     mov    dx,offset _16_bit_slot_msg    ;print the slot size.
  1681.     cmp    _16_not_8_bit_slot,0
  1682.     jne    print_parameters_2
  1683.     mov    dx,offset _8_bit_slot_msg
  1684. print_parameters_2:
  1685.     mov    ah,9
  1686.     int    21h
  1687.  
  1688.     ret
  1689.  
  1690.  
  1691. init_586:
  1692. ;enter with bp=io_addr, 586 reset.
  1693.  
  1694. ;
  1695. ; Set the number of transmit and receive buffers according to the
  1696. ; amount of RAM on the adapter.
  1697. ;
  1698.     MOV    AX, Number_of_Tx_Buffers
  1699.     MOV    BX, num_rx_buf_32k
  1700.  
  1701.     cmp    _64K_not_32K,0
  1702.     je    save_number_of_buffers
  1703.  
  1704.     MOV    BX, num_rx_buf_64k
  1705.  
  1706. save_number_of_buffers:
  1707.  
  1708.     MOV    TxBufferCount, AX
  1709.     MOV    RxBufferCount, BX
  1710. ;
  1711. ; initialize SCP.  Move IO frame to top of SCP.
  1712. ;
  1713.     LEA    DX, [bp].@SMB_Ptr
  1714.     MOV    AX, OFFSET scp
  1715.     OUT    DX, AX
  1716. ;
  1717. ; Write initial SCP values:
  1718. ;    bus width    0 = 16 bit   1 = 8 bit.
  1719. ;    ISCP address    always found at address 000000.
  1720. ;
  1721.     LEA    DX, [BP].@SCP_SystemBus
  1722.     MOV    AL, bus_width
  1723.     OUT    DX, AX
  1724.  
  1725.     LEA    DX, [BP].@SCP_ISCP_Ptr_low
  1726.     XOR    AX, AX
  1727.     OUT    DX, AX
  1728.     LEA    DX, [BP].@SCP_ISCP_Ptr_high
  1729.     OUT    DX, AX
  1730.  
  1731. ;
  1732. ; Initialize ISCP.  Move IO frame to top of ISCP.  NOTE: AX falls
  1733. ; through as zero.
  1734. ;
  1735.     LEA    DX, [bp].@SMB_Ptr
  1736.     OUT    DX, AX
  1737. ;
  1738. ; Write initial ISCP values:
  1739. ;    ISCP BUSY    1 = Indicates 586 is in initialization
  1740. ;            process.  586 sets this byte to 0 when
  1741. ;            initialization is complete.
  1742. ;
  1743. ;    SCB address     Always 000008
  1744. ;
  1745.     LEA    DX, [BP].@iscp_busy
  1746.     MOV    AX, initialize_586
  1747.     OUT    DX, AX
  1748.  
  1749.     LEA    DX, [BP].@ISCP_SCB_Ptr_low
  1750.     XOR    AX, AX
  1751.     OUT    DX, AX
  1752.     LEA    DX, [BP].@ISCP_SCB_Ptr_high
  1753.     OUT    DX, AX
  1754.     LEA    DX, [BP].@iscp_scb_offset
  1755.     MOV    AX, OFFSET scb
  1756.     OUT    DX, AX
  1757.  
  1758. ;
  1759. ; Initialize SCB.  Move Write Ptr to top of SCB.  NOTE: AX falls
  1760. ; through as offset to SCB.
  1761. ;
  1762.     XOR    AX, AX
  1763.     LEA    DX, [BP].@SCB_Status
  1764.     OUT    DX, AX
  1765.     LEA    DX, [BP].@SCB_Command
  1766.     OUT    DX, AX
  1767.     LEA    DX, [BP].@SCB_CommandList
  1768.     OUT    DX, AX
  1769.     LEA    DX, [BP].@SCB_RecBlockList
  1770.     OUT    DX, AX
  1771.     LEA    DX, [BP].@SCB_CRC_Errors
  1772.     OUT    DX, AX
  1773.     LEA    DX, [BP].@SCB_ALN_Errors
  1774.     OUT    DX, AX
  1775.     LEA    DX, [BP].@SCB_RSC_Errors
  1776.     OUT    DX, AX
  1777.     LEA    DX, [BP].@SCB_OVR_Errors
  1778.     OUT    DX, AX
  1779.  
  1780. ;
  1781. ; Initialize Receive Block(s).  First set head pointer and link from
  1782. ; SCB to first frame descriptor.  NOTE: IO frame points to ISCB.
  1783. ; The SCB link field can be addresses becasue the SCB is physically
  1784. ; contiguous to the ISCB.
  1785. ;
  1786.     mov    ax,offset Receive_Blocks
  1787.     lea    dx, [bp].@SCB_RecBlockList    ;IO address of SCB RF link
  1788.     out    dx, ax
  1789.  
  1790. ;
  1791. ; Initialize the frame descriptor structures.  Move the Write ptr
  1792. ; the top of the current frame descriptor.  AX falls through with the
  1793. ; offset to the first frame descriptor.  DI is used to keep track of
  1794. ; the address of the current frame descriptor.  The frame descriptor,
  1795. ; receive buffer descriptor, and receive buffer are all contiguous in
  1796. ; memory, and make up the frame descriptor structure.
  1797. ;
  1798.     MOV    DI, AX                ;DI is current frame descriptor
  1799.     MOV    RECEIVE_HEAD, DI
  1800.     MOV    CX, RxBufferCount        ;CX is number of frame
  1801.                         ; descriptors to initialize.
  1802. init_receive_frames:
  1803.  
  1804.     LEA    DX, [bp].@SMB_Ptr
  1805.     MOV    AX, DI                ; descriptor.
  1806.     OUT    DX, AX
  1807.  
  1808. ;
  1809. ; Init Frame Descriptor (FD).
  1810. ;
  1811.     XOR    AX, AX                ;Init frame descriptor status
  1812.     LEA    DX, [BP+4000H]
  1813.     OUT    DX, AX                ; and command to zero.
  1814.     LEA    DX, [BP+4002H]
  1815.     OUT    DX, AX
  1816.  
  1817.     MOV    AX, RECEIVE_HEAD        ;Init frame descriptors link
  1818.     CMP    CX, 1                ; to next frame descriptor.
  1819.     JE    next_receive_link        ; If this is the last receive
  1820.                         ; block, then set its link to
  1821.     LEA    AX, [DI+SIZE ReceiveBlock]    ; the first receive block.
  1822.  
  1823. next_receive_link:
  1824.  
  1825.     LEA    DX, [BP+4004H]
  1826.     OUT    DX, AX
  1827.  
  1828.     LEA    AX, [DI+OFFSET RBD_ByteCount] ;Init frame descriptors
  1829.     LEA    DX, [BP+4006H]
  1830.     OUT    DX, AX            ; link to its receive buffer descriptor.
  1831. ;
  1832. ; Init Receive Buffer Descriptor (RBD).
  1833. ;
  1834.     LEA    DX, [BP+4008H]
  1835.     OUT    DX, AX            ;Init the RBD Actual count to zero.
  1836.  
  1837.     MOV    AX, -1            ;Init the RBD link to next RBD
  1838.     LEA    DX, [BP+400AH]
  1839.     OUT    DX, AX            ; to minus 1 (unused link).
  1840.  
  1841.     LEA    AX, [DI+RB_Data]    ;Init the RDB link to the data
  1842.     LEA    DX, [BP+400CH]
  1843.     OUT    DX, AX            ; buffer.
  1844.     XOR    AX, AX
  1845.     LEA    DX, [BP+400EH]
  1846.     OUT    DX, AX
  1847.  
  1848.     MOV    AX, RxBufferSize OR BIT_EL    ;Init the RBD count and status
  1849.     LEA    DX, [BP+8000H]
  1850.     OUT    DX, AX
  1851.  
  1852.     MOV    RECEIVE_TAIL, DI    ;Set receive tail pointer.
  1853.     ADD    DI, SIZE ReceiveBlock    ;Point DI to next frame
  1854.     LOOP    init_receive_frames    ; descriptor.
  1855. ;
  1856. ; Initialize the send block structures.  Move the Write pointer the
  1857. ; top of the current send block.  AX falls through with address of
  1858. ; first send block.  DI is used to keep track of the address of the
  1859. ; current send block.  The Transmit command block, transmit buffer
  1860. ; descriptor, and transmit buffer are all contiguous in memory, and
  1861. ; make up the send block structure.
  1862. ;
  1863.     MOV    DI, OFFSET send_blocks
  1864.     MOV    CX, TxBufferCount
  1865.  
  1866.     LEA    DX, [BP].@SMB_Ptr
  1867.     XOR    AX, AX
  1868.     OUT    DX, AX
  1869.  
  1870.     MOV    AX, DI
  1871.     LEA    DX, [BP].@SCB_CommandList
  1872.     OUT    DX, AX
  1873.  
  1874. init_send_blocks:
  1875.  
  1876.     LEA    DX, [BP].@SMB_Ptr        ;Set write pointer to send
  1877.     MOV    AX, DI                ; block.
  1878.     OUT    DX, AX
  1879. ;
  1880. ; Init Transmit Control Block (TCB).
  1881. ;
  1882.     XOR    AX, AX            ;Init transmit control block
  1883.     LEA    DX, [BP+4000H]
  1884.     OUT    DX, AX            ; status to zero.
  1885.  
  1886.     LEA    DX, [BP+4002H]
  1887.     OUT    DX, AX            ;Init transmit control block
  1888.                     ; command to anything.  The
  1889.     MOV    AX, offset send_blocks    ; Init transmit control block
  1890.     CMP    CX, 1            ; link to next send block.
  1891.     JE    next_send_link        ; If this is the last send 
  1892.                     ; block, then point it to
  1893.     LEA    AX, [DI+SIZE SendBlock]    ; the first block.
  1894.  
  1895. next_send_link:
  1896.  
  1897.     LEA    DX, [BP+4004H]
  1898.     OUT    DX, AX
  1899.  
  1900.     LEA    AX, [DI+OFFSET TBD_ByteCount]    ;Init transmit control block
  1901.     LEA    DX, [BP+4006H]
  1902.     OUT    DX, AX                ; link to Transmit Buffer
  1903.                         ; descriptor.
  1904. ;
  1905. ; Init Transmit Buffer Descriptor (TBD).
  1906. ;
  1907.     LEA    DX, [BP+4008H]
  1908.     OUT    DX, AX            ;Init Transmit Buffer Descriptor
  1909.                     ;  byte count to anything
  1910.     MOV    AX, -1            ;Init Transmit Buffer Descriptor
  1911.     LEA    DX, [BP+400AH]
  1912.     OUT    DX, AX            ;  link to next TBD.
  1913.  
  1914.     LEA    AX, [DI+OFFSET TB_Data]    ;Init Transmit Buffer Descriptor
  1915.     LEA    DX, [BP+400CH]
  1916.     OUT    DX, AX            ; link to transmit
  1917.     XOR    AX, AX            ; buffer.  Low part of pointer
  1918.     LEA    DX, [BP+400EH]
  1919.     OUT    DX, AX            ; is done first.
  1920.  
  1921.     ADD    DI, SIZE SendBlock        ;Point DI to next send block
  1922.     LOOP    init_send_blocks        ; and loop to initialize it.
  1923.  
  1924. ;
  1925. ; Enable loopback to insure nothing acidently hits the cable while
  1926. ; the 586 gets initialized.
  1927. ;
  1928.     LEA    DX, [BP].@Config
  1929.     IN    AX, DX
  1930.     OR    AL, loopback_enable
  1931.     OUT    DX, AL
  1932. ;
  1933. ; Free the 586 from reset.
  1934. ;
  1935.     CALL    free_586_reset
  1936. ;
  1937. ; Initialize and configure the 586.  Carry flag set means error and
  1938. ; AX will point to error message.
  1939. ;
  1940.     CALL    init_cmd
  1941.     JNZ    init_bart_ram_exit
  1942.  
  1943.     CALL    configure_command
  1944.     JNZ    init_bart_ram_exit
  1945.  
  1946.     CALL    diagnose_command
  1947.     JNZ    init_bart_ram_exit
  1948.  
  1949.     push    cs
  1950.     pop    es
  1951.     mov    si,offset rom_address
  1952.     mov    cx,EADDR_LEN
  1953.     call    set_address
  1954.         jnc     sa_ok
  1955.  
  1956.         mov     dx,offset badset_msg
  1957.         mov     ah,0
  1958.         int 21h
  1959. sa_ok:
  1960. ;
  1961. ; Disable loopback.
  1962. ;
  1963.     LEA    DX, [BP].@Config
  1964.     IN    AX, DX
  1965.     AND    AL, NOT loopback_enable
  1966.     OUT    DX, AL
  1967.  
  1968.     XOR    AX, AX
  1969.  
  1970. init_bart_ram_exit:
  1971.  
  1972.     OR    AX, AX
  1973.     RET
  1974.  
  1975.  
  1976. ; This procedure must wait until the ASIC finishes reset.  This will take
  1977. ; around 240 uSec.  This loop will time out after 500 uSec.
  1978. ;
  1979. five_hundred_micros    EQU    1194
  1980. ;
  1981. reset_board:
  1982. ;enter with bp=io_addr
  1983.  
  1984.     LEA    DX, [BP].@EEPROM_Ctrl
  1985.     MOV    AL, ASIC_Reset
  1986.     OUT    DX, AL
  1987.  
  1988.     XOR    AL, AL
  1989.     OUT    DX, AL
  1990.  
  1991. ;
  1992. ; Get current tick count.  This loop will wait for 500 uSec to pass
  1993. ; before failing.
  1994. ;
  1995.     CALL    ReadTickCounter
  1996.     MOV    BX, AX
  1997.  
  1998. reset_delay:
  1999.  
  2000.     PUSH    BX
  2001.     CALL    check_for_bart_hardware
  2002.     POP    BX
  2003.  
  2004.     CMP    AX, bart_board_id
  2005.     JE    reset_board_exit
  2006.  
  2007.     CALL    ReadTickCounter
  2008.     NEG    AX
  2009.     ADD    AX, BX
  2010.     CMP    AX, five_hundred_micros
  2011.     JB    reset_delay
  2012.  
  2013.     MOV    AX, OFFSET reset_error
  2014.     stc
  2015.     RET
  2016.  
  2017. reset_board_exit:
  2018.  
  2019.     MOV    BX, AX
  2020.     clc
  2021.     RET
  2022.  
  2023.  
  2024. reset_586:
  2025. ;enter with bp = io_addr
  2026.     lea    dx, [bp].@EEPROM_Ctrl
  2027.     mov    al, _586_Reset
  2028.     out    dx, al
  2029.     ret
  2030.  
  2031.  
  2032. free_586_reset:
  2033. ;enter with bp = io_addr
  2034.     lea    dx, [bp].@EEPROM_Ctrl
  2035.     xor    al, al
  2036.     out    dx, al
  2037.     ret
  2038.  
  2039. check_for_bart_hardware:
  2040. ;
  2041. ; Set DX to the auto-id port.
  2042. ;
  2043.     LEA    DX, [BP].@ID_Port
  2044. ;
  2045. ; BX will have board ID when the loop is done.  CX is the loop count.
  2046. ;
  2047.     XOR    BX, BX
  2048.     MOV    CX, 4
  2049.  
  2050. get_board_id_loop:
  2051. ;
  2052. ; Init registers for loop.  CX needs to be used in the loop, and AH
  2053. ; could be set from the last loop.
  2054. ;
  2055.     PUSH    CX
  2056.     XOR    AH, AH
  2057. ;
  2058. ; Read ID port.  See description above.
  2059. ;
  2060.     IN    AL, DX
  2061. ;
  2062. ; Make nibble ID a shift count in CL.
  2063. ;
  2064.     MOV    CL, AL
  2065.     AND    CL, 00000011B
  2066.     SHL    CL, 1
  2067.     SHL    CL, 1
  2068. ;
  2069. ; Move ID nibble to low order bits of AX, then shift then into place.  Put
  2070. ; the board ID nibble into BX.  After four passes, BX will have board ID.
  2071. ;
  2072.     SHR    AL, 1
  2073.     SHR    AL, 1
  2074.     SHR    AL, 1
  2075.     SHR    AL, 1
  2076.     SHL    AX, CL
  2077.     OR    BX, AX
  2078. ;
  2079. ; Recover loop count, and loop.
  2080. ;
  2081.     POP    CX
  2082.     LOOP    get_board_id_loop
  2083. ;
  2084. ; Return board ID in AX.
  2085. ;
  2086.     MOV    AX, BX
  2087.     RET
  2088.  
  2089.  
  2090. ;
  2091. ; Command #1:  Initialize
  2092. ;
  2093. init_cmd:
  2094.     XOR    AX, AX                ; Init command
  2095.     MOV    BX, BIT_CX + BIT_CNA        ; status
  2096.     CALL    issue_command
  2097.     RET
  2098.  
  2099. diagnose_command:
  2100. ;
  2101. ; Set up individual address command block.
  2102. ;
  2103.     MOV    BX, BIT_EL+GA_diagnose
  2104.     CALL    setup_command_block
  2105. ;
  2106. ; Execute the diagnose command.
  2107. ;
  2108.     MOV    AX, CUC_Start
  2109.     MOV    BX, BIT_CNA
  2110.     CALL    issue_command
  2111. ;
  2112. ; Check diagnostics results.
  2113. ;
  2114.     LEA    DX, [BP].@SMB_Ptr        ;Move IO frame to the command
  2115.     MOV    AX, OFFSET cb            ; command block.
  2116.     OUT    DX, AX
  2117.  
  2118.     LEA    DX, [BP].@mem_loc_0        ;Read in the diagnose status
  2119.     IN    AX, DX                ; word.
  2120. ;
  2121. ; Assume 586 failed the test.  Set AX to an error message and exit
  2122. ; with the zero bit cleared.
  2123. ;
  2124.     MOV    BX, AX
  2125.     MOV    AX, OFFSET _586_diagnostic_failure
  2126.  
  2127.     TEST    BX, 0800H            ;Test failure bit.  If set,
  2128.     JNZ    diagnose_exit            ; then error exit.
  2129.  
  2130.     XOR    AX, AX                ;Set AX and zero bit to
  2131.                         ; indicate no error.
  2132. diagnose_exit:
  2133.  
  2134.     RET
  2135.  
  2136.  
  2137. ;
  2138. ; Command #4:  RU_START
  2139. ;
  2140. ru_start:
  2141. ;
  2142. ; Set SCBs pointer to receive blocks at head of list.
  2143. ;
  2144.     lea    dx, [bp].@SCB_RFA        ;Set pointer to receive blocks
  2145.     mov    ax, receive_head        ; to the head of the receive
  2146.     out    dx, ax                ; block list.
  2147. ;
  2148. ; Signal 586 to start the receive unit.  cmd_clear leaves DX pointing
  2149. ; to SCB command register.
  2150. ;
  2151.     cmd_clear
  2152.     mov    ax, ruc_start
  2153.     out    dx, ax
  2154.     issue_CA
  2155.      ret
  2156.  
  2157.  
  2158. find_a_board:
  2159.         mov     bx,offset io_addresses
  2160. no_bart_here:
  2161.         mov     bp,[bx]
  2162.         cmp     bp,0
  2163.         je      no_barts
  2164.         inc     bx
  2165.         inc     bx
  2166.         push    bx
  2167.         call    reset_board
  2168.         pop     bx
  2169.         jc      no_bart_here
  2170.  
  2171.         clc
  2172.         ret
  2173.  
  2174. no_barts:
  2175.         stc
  2176.         ret
  2177.  
  2178. get_system_info:
  2179.         cmp     io_addr,0
  2180.         jne     addr_override
  2181.         call    find_a_board
  2182.         jnc     board_id_ok
  2183.         jmp     bad_or_no_board
  2184.  
  2185. addr_override:
  2186.  
  2187.     MOV    bp, io_addr
  2188.  
  2189. ;
  2190. ; Next, get the bart board ID.  If the ID is not what we expect, then
  2191. ; exit with error code in AX.
  2192. ;
  2193.     call    reset_board
  2194.     jnc    board_id_ok
  2195. ;
  2196. ; Could search for bart board, but we error exit instead.
  2197. ;
  2198. bad_or_no_board:
  2199.  
  2200.     MOV    AX, OFFSET board_not_installed
  2201.     JMP    SHORT get_system_info_exit
  2202.  
  2203. board_id_ok:
  2204.         mov     io_addr,bp
  2205.  
  2206. ;
  2207. ; Since the software will be reading the EEPROM during the
  2208. ; initialization, the 586 needs to be inactive.  This is because the
  2209. ; control lines to the EEPROM are shared between the 586 and this
  2210. ; software.  To keep from getting fouled up, the 586 reset line is
  2211. ; asserted here (now that we have a base IO address, and we know that
  2212. ; the hardware is present).  The 586 is not released from reset until
  2213. ; after its data structures are intialized.
  2214. ;
  2215.     CALL    reset_586
  2216. ;
  2217. ; Validate the EEPROM by doing a checksum.
  2218. ;
  2219.     CALL    check_eeprom
  2220.     JC    get_system_info_exit
  2221. ;
  2222. ; Get the amount of memory on the adapter.  If carry clear, then AX
  2223. ; has memory size.  Else AX has error code.
  2224. ;
  2225.     CALL    test_buffer_memory
  2226.     JC    get_system_info_exit
  2227.  
  2228.     MOV    _64K_not_32K,al
  2229. ;
  2230. ; Get the connection type.  If carry clear, then AL has connection
  2231. ; type.  Otherwise AX has error code.
  2232. ;
  2233.     CALL    get_connection_type
  2234.     JC    get_system_info_exit
  2235.  
  2236.     MOV    connection_type, AL
  2237. ;
  2238. ; Read the Ethernet address out of the EEPROM.
  2239. ;
  2240.     MOV    AX, ee_ethernet_add_high
  2241.     CALL    read_eeprom
  2242.     xchg    ah,al
  2243.     MOV    word ptr rom_address[0], AX
  2244.  
  2245.     MOV    AX, ee_ethernet_add_mid
  2246.     CALL    read_eeprom
  2247.     xchg    ah,al
  2248.     MOV    word ptr rom_address[2], AX
  2249.  
  2250.     MOV    AX, ee_ethernet_add_low
  2251.     CALL    read_eeprom
  2252.     xchg    ah,al
  2253.     MOV    word ptr rom_address[4], AX
  2254.  
  2255.         mov     ax,ee_int
  2256.         call    read_eeprom
  2257.         mov     cl,ee_shift
  2258.         shr     ax,cl
  2259.         mov     encoded_int_no,al
  2260.     mov    bx,offset irq_xlat_table
  2261.         mov     cl,0
  2262. kg:
  2263.         cmp     [bx],al
  2264.         je      found_it
  2265.         inc     bx
  2266.         inc     cl
  2267.         jmp     kg
  2268. found_it:
  2269.     mov    int_no,cl
  2270.  
  2271. ;
  2272. ; Get the Slot width.  If carry clear, then AL has the slot width.
  2273. ; Otherwise AX has error code.
  2274. ;
  2275.     LEA    DX, [BP].@Config
  2276.     IN    AL, DX
  2277. ;
  2278. ; Slot width is found in the adapters configuration register.
  2279. ;
  2280.     and    al, slot_width_mask
  2281.     mov    _16_not_8_bit_slot, al
  2282.  
  2283.     xor    ax, AX
  2284.  
  2285. get_system_info_exit:
  2286.  
  2287.     OR    AX, AX
  2288.     RET
  2289.  
  2290. ;
  2291. ;
  2292. ; Return connection type in AL with carry clear.  Otherwise return AX with
  2293. ; unable_to_read_eeprom error code and carry set.
  2294. ;
  2295. ;
  2296. get_connection_type:
  2297.  
  2298. ;
  2299. ; Read the connection address from the EEPROM.
  2300. ;
  2301.     MOV    AX, connection_address
  2302.     CALL    read_eeprom        ;Read_eeprom does not trash DI
  2303.  
  2304. ;
  2305. ; Assume AUI type connection.  Check connection fields to see if this
  2306. ; is a BNC connection.  Jump if it is BNC.
  2307. ;
  2308.     MOV    BL, aui
  2309.     TEST    AX, connection_field
  2310.     JZ    get_connection_type_ret
  2311.  
  2312. ;
  2313. ; Here if NOT BNC.  Must read another EEPROM word to tell if AUI or
  2314. ; TPE.  Assume AUI and then check for TPE.
  2315. ;
  2316.     MOV    AX, tpe_address
  2317.     CALL    read_eeprom        ;Read_eeprom does not trash DI
  2318.  
  2319. ;
  2320. ; Check for AUI connection.
  2321. ;
  2322.         mov     bl,bnc
  2323.     TEST    AX, TPE_type_field
  2324.     JZ    get_connection_type_ret
  2325.  
  2326. ;
  2327. ; Here if TPE type connection.
  2328. ;
  2329.     MOV    BL, TPE
  2330.  
  2331. get_connection_type_ret:
  2332.  
  2333.     MOV    AL, BL
  2334.  
  2335.     CLC
  2336.     RET
  2337.  
  2338.  
  2339. ;
  2340. ;
  2341. ; Do a checksum on the EEPROM.  Retrun carry set and AX pointing to an error
  2342. ; message if checksum is bad.  Otherwise return carry clear.
  2343. ;
  2344. ; The checksum is the same as the board ID.
  2345. ;
  2346. check_eeprom:
  2347.  
  2348.     mov    cx, 40h
  2349.     xor    bx, bx
  2350.  
  2351. checksum_loop:
  2352.  
  2353.     mov    ax, cx
  2354.     dec    ax
  2355.     call    read_eeprom
  2356.  
  2357.     add    bx, ax
  2358.     loop    checksum_loop
  2359.  
  2360.     cmp    bx, bart_board_id
  2361.     jne    checksum_error
  2362.  
  2363.     clc
  2364.     ret
  2365.  
  2366. checksum_error:
  2367.  
  2368.     mov    ax, offset eeprom_checksum_error
  2369.     stc
  2370.     ret
  2371.  
  2372.  
  2373. test_buffer_memory:
  2374. ;enter with bp=io_addr
  2375. ;exit with nc if no error, or cy and di -> address in error.
  2376.  
  2377. ; Set up SI with the maximum number of words to test.  If there is an
  2378. ; error testing the high 32K of memory, then we will restart the
  2379. ; test at 32K.  When the tests pass, the memory size is passed back
  2380. ; in AX.
  2381. ;
  2382.     mov    si, 64 * (1024/2)
  2383. ;
  2384. ; Warm up the buffer memory with 16 word writes.
  2385. ;
  2386.     mov    cx, 16
  2387.     call    write_zeros
  2388.  
  2389.     cmp    cs:is_186,0
  2390.     je    restart_memory_tests
  2391.  
  2392.     jmp    short start_memory_tests
  2393.  
  2394. restart_memory_tests:
  2395. ;
  2396. ; Here if error testing memory and SI is set to 64K buffer size.
  2397. ; We restart the tests for 32K buffer only.  If an error occurs
  2398. ; with SI set to 32K, then a memory error is reported.
  2399. ;
  2400.     mov    si, 32 * (1024/2)
  2401.  
  2402. start_memory_tests:
  2403. ;
  2404. ; Zero RAM.  Set write pointer to the base address and then fill the
  2405. ; bufffer memory with zeros.
  2406. ;
  2407.     mov    cx, si
  2408.     call    write_zeros
  2409.  
  2410.     call    word_memory_test_pattern
  2411.     jc    buffer_mem_error_exit
  2412.  
  2413.     cmp    cs:is_186,0
  2414.     je    _8088_quick_exit
  2415.  
  2416.     mov    cx, si
  2417.     call    write_zeros
  2418.  
  2419.     call    byte_memory_test_pattern
  2420.     jc    buffer_mem_error_exit
  2421.  
  2422. _8088_quick_exit:
  2423. ;
  2424. ; Zero RAM.  Set write pointer to the base address and then fill the
  2425. ; bufffer memory with zeros.
  2426. ;
  2427.     mov    cx, si
  2428.     call    write_zeros
  2429.  
  2430. ;
  2431. ; Set _64K_not_32K to the size of the memory that passed diagnostics.
  2432. ;
  2433.     cmp    si, 32 * (1024/2)    ;did we quit at 32K
  2434.     je    buffer_mem_exit        ;yes, we only have 32K.
  2435.  
  2436.     mov    _64K_not_32K,1        ;no, we must have 64K.
  2437.  
  2438. buffer_mem_exit:
  2439.     clc
  2440.     ret
  2441.  
  2442. buffer_mem_error_exit:
  2443. ;
  2444. ; If error occured, and SI is not set for 32K, then retry tests with
  2445. ; SI set for 32K.  If the error occurs and the size is 32K, then the
  2446. ; Bart board memory is bad.
  2447. ;
  2448.     CMP    SI, 32 * (1024/2)
  2449.     JNE    restart_memory_tests
  2450.  
  2451.     MOV    AX, OFFSET buffer_memory_error
  2452.     STC                    ;Set carry to indicate error.
  2453.     RET
  2454.  
  2455.  
  2456. write_zeros:
  2457. ;enter with bp=io_addr, cx=number of zero words to write.
  2458. ;
  2459. ; Move write pointer to the beginning of the buffer memory.
  2460. ;
  2461.     LEA    DX, [BP].@Write_Ptr
  2462.     XOR    AX, AX
  2463.     OUT    DX, AX
  2464. ;
  2465. ; Set DX to the data register and write out zeros CX times.
  2466. ;
  2467.     mov    dx, bp            ;@Data_Reg
  2468. warm_up:
  2469.     out    dx, ax
  2470.     loop    warm_up
  2471.     ret
  2472.  
  2473.  
  2474. word_memory_test_pattern:
  2475. ;enter with si = number of words to test.
  2476.  
  2477. ;
  2478. ; Set CX to number of words to test.  Set BX to beginning og pattern.
  2479. ;
  2480.     MOV    CX, SI
  2481.     MOV    BX, 1
  2482.  
  2483. ;
  2484. ; Set DI to beginning of the buffer.
  2485. ;
  2486.     XOR    DI, DI
  2487.  
  2488. word_inc_pattern:
  2489.  
  2490.     CALL    loop_set_up
  2491.     IN    AX, DX
  2492.     OR    AX, AX
  2493.     JNE    word_memory_test_pattern_error
  2494.  
  2495. ;
  2496. ; Write Test Pattern.
  2497. ;
  2498.     MOV    AX, BX
  2499.     OUT    DX, AX
  2500.  
  2501. ;
  2502. ; Increment BX to next test pattern value.
  2503. ;
  2504.     ADD    BX, 3
  2505.  
  2506. ;
  2507. ; Increment DI to next test memory location.
  2508. ;
  2509.     ADD    DI, 2
  2510.     LOOP    word_inc_pattern
  2511.  
  2512. ;
  2513. ; Set Read pointer to beginning of buffer.
  2514. ;
  2515.     LEA    DX, [BP].@read_ptr
  2516.     XOR    AX, AX
  2517.     OUT    DX, AX
  2518.     MOV    DX, BP            ;@Data_Reg
  2519.  
  2520. ;
  2521. ; Set CX to number of words to test.  Set BX to beginning og pattern.
  2522. ;
  2523.     MOV    CX, SI
  2524.     MOV    BX, 1
  2525.  
  2526. word_check_pattern:
  2527.  
  2528.     IN    AX, DX
  2529.     CMP    AX, BX
  2530.     JNE    word_memory_test_pattern_error
  2531.  
  2532. ;
  2533. ; Increment BX to next test pattern value.
  2534. ;
  2535.     ADD    BX, 3
  2536.  
  2537.     LOOP    word_check_pattern
  2538.  
  2539.     CLC
  2540.     RET
  2541.  
  2542. word_memory_test_pattern_error:
  2543.  
  2544.     STC
  2545.     RET
  2546.  
  2547.  
  2548. byte_memory_test_pattern:
  2549. ;enter with si = number of bytes to test.
  2550.  
  2551. ;
  2552. ; Set CX to number of bytes to test.  Set BX to beginning of pattern.
  2553. ;
  2554.     MOV    CX, SI
  2555.     SHL    CX, 1
  2556.     MOV    BL, 1
  2557.  
  2558. ;
  2559. ; Set DI to beginning of the buffer.
  2560. ;
  2561.     XOR    DI, DI
  2562.  
  2563. byte_inc_pattern:
  2564.  
  2565.      CALL    loop_set_up
  2566.     IN    AL, DX
  2567.     OR    AL, AL
  2568.     JNE    byte_memory_test_pattern_error
  2569.  
  2570. ;
  2571. ; Write Test Pattern.
  2572. ;
  2573.     MOV    AL, BL
  2574.     OUT    DX, AL
  2575.  
  2576. ;
  2577. ; Increment BX to next test pattern value.
  2578. ;
  2579.     ADD    BL, 3
  2580.  
  2581. ;
  2582. ; Increment DI to next test memory location.
  2583. ;
  2584.     INC    DI
  2585.     
  2586.     LOOP    byte_inc_pattern
  2587.  
  2588. ;
  2589. ; Set Read pointer to beginning of buffer.
  2590. ;
  2591.     LEA    DX, [BP].@read_ptr
  2592.     XOR    AX, AX
  2593.     OUT    DX, AX
  2594.     MOV    DX, BP            ;@Data_Reg
  2595.  
  2596. ;
  2597. ; Set CX to number of bytes to test.  Set BX to beginning of pattern.
  2598. ;
  2599.     MOV    CX, SI
  2600.     SHL    CX, 1
  2601.     MOV    BL, 1
  2602.  
  2603. byte_check_pattern:
  2604.  
  2605.     IN    AL, DX
  2606.     CMP    AL, BL
  2607.     JNE    byte_memory_test_pattern_error
  2608.  
  2609. ;
  2610. ; Increment BX to next test pattern value.
  2611. ;
  2612.     add    bl, 3
  2613.  
  2614.     loop    byte_check_pattern
  2615.  
  2616.     clc
  2617.     ret
  2618.  
  2619. byte_memory_test_pattern_error:
  2620.  
  2621.     stc
  2622.     ret
  2623.  
  2624. loop_set_up:
  2625. ;enter with bp=io_addr, di=buffer address.
  2626. ;exit with ax=value at di, dx=I/O address to access buffer memory at DI
  2627.  
  2628.     PUSH    DI
  2629.  
  2630.     MOV    AX, DI                  ;SMB_Ptr must be on 16 byte
  2631.     AND    AX, 0FFE0H
  2632.     AND    DI, 0001FH
  2633.  
  2634.     LEA    DX, [BP].@SMB_Ptr        ;Set IO page frame to the
  2635.     OUT    DX, AX
  2636.  
  2637.  
  2638.     TEST    DI, 0010H
  2639.     JZ    loop_set_up_1
  2640.  
  2641.     ADD    DI, @MEM_LOC_0
  2642.  
  2643. loop_set_up_1:
  2644.     AND    DI, 0FFEFH
  2645.     LEA    DX, [BP+DI].@MEM_LOC_0        ;Set DX for IO from buffer and
  2646.  
  2647.     POP    DI
  2648.  
  2649.     RET
  2650.  
  2651.  
  2652. read_eeprom:
  2653. ;enter with bp=io_addr, ax = EEPROM location.
  2654. ;exit with ax = EEPROM contents.
  2655. ;preserves di.
  2656.     push    di
  2657.     push    bx
  2658.     push    cx
  2659.  
  2660. ;  Point to EEPROM control port.
  2661.  
  2662.     lea    dx, [bp].@eeprom_ctrl
  2663.     mov    bx, ax
  2664.  
  2665. ; Select the EEPROM.  Mask off the ASIC and 586 reset bits and set
  2666. ; the ee_cs bit in the EEPROM control register.
  2667.  
  2668.     in    al, dx
  2669.     and    al, 10110010b
  2670.     or    al, ee_cs
  2671.     out    dx, al
  2672.  
  2673. ; Write out read opcode and EEPROM location.
  2674.  
  2675.     mov    ax, eeprom_read_opcode        ;Set AX to READ opcode and
  2676.     mov    cx, 3                ;Send it to the EEPROM circuit
  2677.     call    shift_bits_out
  2678.  
  2679.     mov    ax, bx                ;Tell EEPROM which register is
  2680.      mov    cx, 6                ; to be read.  6 bit address.
  2681.     call    shift_bits_out
  2682.  
  2683.     call    shift_bits_in            ;AX gets EEPROM register
  2684.  
  2685.     call    eeprom_clean_up            ;Leave EEPROM in known state.
  2686.  
  2687.     pop    cx
  2688.     pop    bx
  2689.     pop    di
  2690.     ret
  2691.  
  2692.  
  2693. shift_bits_out:
  2694. ;enter with ax=data to be shifted, cx=# of bits to be shifted.
  2695.  
  2696.     push    bx
  2697.  
  2698. ; Data bits are right justified in the AX register.  Move the data
  2699. ; into BX and left justify it.  This will cause addresses to to
  2700. ; be sent to the EEPROM high order bit first.
  2701.  
  2702.     mov    bx, ax
  2703.     mov    ch, 16
  2704.     sub    ch, cl
  2705.     xchg    cl, ch
  2706.     shl    bx, cl
  2707.     xchg    cl, ch
  2708.     xor    ch, ch
  2709.  
  2710. ; Get the EEPROM control register into AL.  Mask of the ASIC asn 586
  2711. ; reset bits.
  2712.  
  2713.     in    al, dx
  2714.     and    al, 10111111b
  2715.  
  2716. ; Set or clear DI bit in EEPROM control register based on value of
  2717. ; data in BX.
  2718.  
  2719. out_shift_loop:
  2720.     and    al, not ee_di            ;Assume data bit will be zero
  2721.  
  2722.     rcl    bx, 1                ;Is the data bit a one?
  2723.     jnc    out_with_it            ;No
  2724.     or    al, ee_di            ;Yes
  2725. out_with_it:
  2726.     out    dx, al                ;Output a 0 or 1 on data pin
  2727.  
  2728. ; Set up time for data is .4 Microseconds.  So to be safe (incase of
  2729. ; this software is run on a cray), call delay.
  2730.     mov    di, 1
  2731.     call    eeprom_delay
  2732.  
  2733.     call    raise_eeprom_clock    ; Clock the data into the EEPROM.
  2734.     call    lower_eeprom_clock
  2735.     loop    out_shift_loop        ;Send next bit
  2736.  
  2737.     and    al, not ee_di        ;Force data bit to zero
  2738.     out    dx, al            ;Output a 0 on data pin
  2739.  
  2740.     pop    bx
  2741.  
  2742.     ret
  2743.  
  2744. shift_bits_in:
  2745. ;exit with ax = register contents.
  2746.     push    bx
  2747.     push    cx
  2748.  
  2749. ; BX will receive the 16 bits read from the EEPROM.  Data is valid in 
  2750. ; data out bit (DO) when clock is high.  There for, this procedure 
  2751. ; raises clock and waits a minimum amount of time.  DO is read, and 
  2752. ; clock is lowered.
  2753.  
  2754.     in    al, dx                ;Init AL to eeprom control
  2755.     and    al, 10111111b            ; register.
  2756.  
  2757.     xor    bx, bx                ;Init holding register
  2758.     mov    cx, 16                ;We'll shift in 16 bits
  2759.  
  2760. in_shift_loop:
  2761.     shl    bx, 1            ;Adjust holding register for 
  2762.                     ; next bit
  2763.     call    raise_eeprom_clock
  2764.  
  2765.     in    al, dx
  2766.     and    al, 10111111b
  2767.  
  2768.     test    al, ee_do        ;Was the data bit a one?
  2769.     jz    in_eeprom_delay        ;No
  2770.  
  2771.     or    bx, 1            ;Yes, reflect data bit state 
  2772.                     ; in holding register.
  2773.  
  2774. in_eeprom_delay:
  2775.     call    lower_eeprom_clock
  2776.     loop    in_shift_loop        ;CONTINUE
  2777.  
  2778.     mov    ax, bx            ;AX = data
  2779.  
  2780.     pop    cx
  2781.     pop    bx
  2782.     ret
  2783.  
  2784. raise_eeprom_clock:
  2785.     or    al, ee_sk        ;Clock the bit out by raising 
  2786.     jmp    short eeprom_clock_common
  2787. lower_eeprom_clock:
  2788.     and    al, not ee_sk            ;Lower ee_sk
  2789. eeprom_clock_common:
  2790.     out    dx, al
  2791.     mov    di, ee_tick
  2792.     call    eeprom_delay            ;Waste time
  2793.     ret
  2794.  
  2795.  
  2796. ; Lower EEPROM chip select and DI.
  2797. ; Clock EEPROM twice and leave clock low.
  2798.  
  2799. eeprom_clean_up:
  2800.  
  2801.     push    ax
  2802.  
  2803.      in    al, dx
  2804.     and    al, 10111111b
  2805.     and    al, not (ee_cs or ee_di)
  2806.     out    dx, al
  2807.  
  2808.     call    raise_eeprom_clock
  2809.     call    lower_eeprom_clock
  2810.  
  2811.     pop    ax
  2812.     ret
  2813.  
  2814. ; DI has number of 838 Nanoseconds clock counts
  2815. eeprom_delay:
  2816.  
  2817.     push    ax
  2818.     push    bx
  2819.     push    dx
  2820.  
  2821.     call    readtickcounter
  2822.     mov    bx, ax
  2823.  
  2824. eeprom_delay_loop:
  2825.  
  2826.     call    readtickcounter
  2827.     neg    ax
  2828.     add    ax, bx
  2829.     cmp    ax, di
  2830.     jb    eeprom_delay_loop
  2831.  
  2832.     pop    dx
  2833.     pop    bx
  2834.     pop    ax
  2835.     ret
  2836.  
  2837. iochrdy_test:
  2838. ; First test to see if the driver is supposed to run this test.
  2839.     MOV    AX, lock_bit_address
  2840.     CALL    read_eeprom
  2841.  
  2842.     TEST    AX, lock_bit_mask
  2843.     JNZ    iochrdy_test_exit
  2844. ; Get the configuration register.
  2845.  
  2846.     LEA    DX, [BP].@config
  2847.     IN    AL, DX
  2848.  
  2849. ; Set the iochrdy test bit with and set iochrdy to late.
  2850.     OR    AL, iochrdy_test_mask+iochrdy_late
  2851.     CLI
  2852.     OUT    DX, AL
  2853.  
  2854. ; Test IOCHRDY with IO.
  2855.     LEA    DX, [BP].@mem_loc_0
  2856.     IN    AX, DX
  2857.  
  2858. ; Read in the results of the test.  Save results in BL.
  2859.     LEA    DX, [BP].@config
  2860.     IN    AL, DX
  2861.     MOV    BL, AL
  2862.  
  2863. ; Turn iochrdy test off.
  2864.     AND    AL, NOT iochrdy_test_mask
  2865.     OUT    DX, AL
  2866.     STI
  2867.  
  2868. ; Test results.  Exit if IOCHRDY_LATE bit is set correctly.
  2869.     TEST    BL, iochrdy_test_result
  2870.     JZ    iochrdy_test_exit
  2871.  
  2872. ; Here if test failed.  Clear the 16 bit override bit (force 8 bit
  2873. ; transfers) and print a warning message.
  2874.     AND    AL, NOT _16_bit_override_bit
  2875.     OUT    DX, AL
  2876.  
  2877.     mov    dx, offset iochrdy_problem
  2878.         mov     ah,9
  2879.     int     21h
  2880.  
  2881.  
  2882. iochrdy_test_exit:
  2883.  
  2884.     RET
  2885.  
  2886.  
  2887.  
  2888. iochrdy_problem                 DB      10,13,"IOCHRDY Problem.  Bart forced into 8 Bit Mode.$"
  2889. buffer_memory_error        DB    10,13,"Memory error on the Bart board$"
  2890.  
  2891. reset_error            DB    10,13,"ASIC reset failure on Bart board$"
  2892.  
  2893. _586_diagnostic_failure    DB    10,13,"82586 diagnostic failure on the "
  2894.                 DB          "Bart board$"
  2895.  
  2896. _586_not_responding_msg    DB    10,13,"82586 did not respond to command "
  2897.                 DB          "on the Bart board$"
  2898.  
  2899. command_unit_not_idle    DB    10,13,"82586 command unit is not "
  2900.                 DB          "responding on the Bart board$"
  2901.  
  2902. invalid_int_no        LABEL    WORD
  2903. invalid_int_number        DB    10,13,"Bart board IRQ/Interrupt number "
  2904.                 DB          "not specified correctly$"
  2905.  
  2906. eeprom_checksum_error    DB    10,13,"EEPROM failed checksum$"
  2907.  
  2908. Board_Not_Installed        DB    10,13,"Bart Board not found$"
  2909.  
  2910. irq_config_error        DB    10,13,"IRQ selection is for 16 bit slot "
  2911.                 DB          "only.$"
  2912.  
  2913. code    ends
  2914.  
  2915.     end
  2916.